From 806d87e779dc829dfbf126155e015f766a41b972 Mon Sep 17 00:00:00 2001 From: voltgizerz Date: Sat, 10 Dec 2022 17:55:15 +0700 Subject: [PATCH 1/5] Revert "Merge pull request #7 from voltgizerz/develop" This reverts commit 00abb8ed8e18bdb451c65fd93e3725cc39f743f8, reversing changes made to 2837a80e5e6b1d21fa7d17d36d53e2c4f4379125. --- .env.example | 6 +- README.md | 13 +- auth/jwt.go | 44 --- auth/middleware.go | 30 +- errors/error.go | 13 +- go.mod | 1 - go.sum | 2 - graph/generated/generated.go | 373 -------------------- graph/resolvers/authorization.resolvers.go | 40 --- graph/resolvers/create_pokemon.resolvers.go | 2 +- graph/resolvers/delete_pokemon.resolvers.go | 2 +- graph/resolvers/pokemon.resolvers.go | 8 +- graph/resolvers/pokemons.resolvers.go | 2 +- graph/resolvers/resolver.go | 3 - graph/resolvers/types.resolvers.go | 2 +- graph/resolvers/update_pokemon.resolvers.go | 2 +- graph/schemas/authorization.graphqls | 14 - models/models_gen.go | 11 - server.go | 3 - service/auth.service.go | 78 ---- 20 files changed, 32 insertions(+), 617 deletions(-) delete mode 100644 auth/jwt.go delete mode 100644 graph/resolvers/authorization.resolvers.go delete mode 100644 graph/schemas/authorization.graphqls delete mode 100644 service/auth.service.go diff --git a/.env.example b/.env.example index 074c657..ba47f25 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,4 @@ DATA_SOURCE="your own db" DB_HOST_LOCAL= root:@tcp(localhost)/pokemon?charset=utf8mb4&parseTime=True&loc=Local ENV=development -GIN_MODE=debug -JWT_SECRET_KEY="secret" -JWT_ISSUER="jhon" -LOGIN_USERNAME="felix" -LOGIN_PASSWORD="felix" \ No newline at end of file +GIN_MODE=debug \ No newline at end of file diff --git a/README.md b/README.md index f5f0f6c..3cfa4f1 100644 --- a/README.md +++ b/README.md @@ -51,21 +51,12 @@ make format ``` { - "Authorization":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzA2NzI0MjQsImlzcyI6Impob24iLCJVc2VySUQiOjgxLCJVc2VybmFtZSI6ImZlbGl4IiwiTmFtZSI6IkZlbGl4IiwiSXNBZG1pbiI6dHJ1ZSwiRXhwaXJlc0F0IjoxNjcwNjcyNDI0fQ.noKdYN3fhr7iwQmlDy1xYn1FqLsZ4gY-ORkWf3oeP_I" + "user_id": 2323 } ``` 💡 **Query** -* Login get token -``` -query login { - login(input: {username: "felix", password: "felix"}) { - success - message - token - } -} -``` + * Show all data pokemon (limit, offset, sort) ``` query pokemons { diff --git a/auth/jwt.go b/auth/jwt.go deleted file mode 100644 index d560ac5..0000000 --- a/auth/jwt.go +++ /dev/null @@ -1,44 +0,0 @@ -package auth - -import ( - "errors" - "os" - "time" - - "github.com/golang-jwt/jwt" -) - -// JwtClaims - . -type JwtClaims struct { - jwt.StandardClaims - UserID int - Username string - Name string - IsAdmin bool - ExpiresAt int64 -} - -// ValidateAuthorization - validate jwt token. -func ValidateAuthorization(signedToken string) (claims *JwtClaims, err error) { - token, err := jwt.ParseWithClaims( - signedToken, - &JwtClaims{}, - func(token *jwt.Token) (interface{}, error) { - return []byte(os.Getenv("JWT_SECRET_KEY")), nil - }, - ) - if err != nil { - return - } - - claims, ok := token.Claims.(*JwtClaims) - if !ok { - return nil, errors.New("couldn't parse claims") - } - - if claims.StandardClaims.ExpiresAt < time.Now().Local().Unix() { - return nil, errors.New("jwt is expired") - } - - return claims, nil -} diff --git a/auth/middleware.go b/auth/middleware.go index 9031145..3b6e6d8 100644 --- a/auth/middleware.go +++ b/auth/middleware.go @@ -3,6 +3,7 @@ package auth import ( "context" "net/http" + "strconv" "github.com/go-graphql/errors" ) @@ -17,27 +18,24 @@ const ( // User - a stand-in for our database backed user object type User struct { - UserID int - Username string - Name string - IsAdmin bool + UserID int + Name string + IsAdmin bool } // Middleware - handle auth data func Middleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - user := &User{} - authToken := r.Header.Get("authorization") - - if authToken != "" { - data, err := ValidateAuthorization(authToken) - if err == nil { - user.IsAdmin = data.IsAdmin - user.Name = data.Name - user.Username = data.Username - user.UserID = data.UserID - } + userID, err := strconv.Atoi(r.Header.Get("user_id")) + if err != nil { + userID = 0 // Default to 0 when header user_id not set + } + + user := &User{ + UserID: userID, + Name: "felix", + IsAdmin: true, } // put it in context @@ -54,7 +52,7 @@ func Middleware() func(http.Handler) http.Handler { func ForContext(ctx context.Context) (*User, error) { raw, _ := ctx.Value(CONTEXT_USER).(*User) if raw.UserID == 0 { - return nil, errors.ErrorNoAuthorization + return nil, errors.ErrorHeaderNotSet } return raw, nil diff --git a/errors/error.go b/errors/error.go index d8dc0d2..c5be62a 100644 --- a/errors/error.go +++ b/errors/error.go @@ -2,13 +2,8 @@ package errors import "errors" -var ( - // ErrorOccur - . - ErrorOccur = errors.New("error") +// ErrorOccur - . +var ErrorOccur = errors.New("error") - // ErrorNoAuthorization - . - ErrorNoAuthorization = errors.New("authorization is not valid") - - // ErrorAuth - . - ErrorAuth = errors.New("username or Password invalid") -) +// ErrorHeaderNotSet - . +var ErrorHeaderNotSet = errors.New("header user_id is not set") diff --git a/go.mod b/go.mod index 78f0f48..0fe1dfb 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ require ( github.com/agnivade/levenshtein v1.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/mock v1.6.0 github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect diff --git a/go.sum b/go.sum index f3369ad..4696365 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,6 @@ github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 784476e..afbf67e 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -55,12 +55,6 @@ type ComplexityRoot struct { Success func(childComplexity int) int } - LoginPayload struct { - Message func(childComplexity int) int - Success func(childComplexity int) int - Token func(childComplexity int) int - } - Mutation struct { CreatePokemon func(childComplexity int, input models.CreatePokemonInput) int DeletePokemon func(childComplexity int, input models.DeletePokemonInput) int @@ -84,7 +78,6 @@ type ComplexityRoot struct { } Query struct { - Login func(childComplexity int, input models.LoginInput) int Pokemon func(childComplexity int, pokemonID int) int Pokemons func(childComplexity int, limit *int, offset *int) int Types func(childComplexity int, typeID *int) int @@ -116,7 +109,6 @@ type PokemonResolver interface { Types(ctx context.Context, obj *models.Pokemon) ([]*models.Type, error) } type QueryResolver interface { - Login(ctx context.Context, input models.LoginInput) (*models.LoginPayload, error) Pokemon(ctx context.Context, pokemonID int) (*models.Pokemon, error) Pokemons(ctx context.Context, limit *int, offset *int) ([]*models.Pokemon, error) Types(ctx context.Context, typeID *int) ([]*models.Type, error) @@ -158,27 +150,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DeletePokemonPayload.Success(childComplexity), true - case "LoginPayload.message": - if e.complexity.LoginPayload.Message == nil { - break - } - - return e.complexity.LoginPayload.Message(childComplexity), true - - case "LoginPayload.success": - if e.complexity.LoginPayload.Success == nil { - break - } - - return e.complexity.LoginPayload.Success(childComplexity), true - - case "LoginPayload.token": - if e.complexity.LoginPayload.Token == nil { - break - } - - return e.complexity.LoginPayload.Token(childComplexity), true - case "Mutation.createPokemon": if e.complexity.Mutation.CreatePokemon == nil { break @@ -285,18 +256,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PokemonType.TypeID(childComplexity), true - case "Query.login": - if e.complexity.Query.Login == nil { - break - } - - args, err := ec.field_Query_login_args(context.TODO(), rawArgs) - if err != nil { - return 0, false - } - - return e.complexity.Query.Login(childComplexity, args["input"].(models.LoginInput)), true - case "Query.pokemon": if e.complexity.Query.Pokemon == nil { break @@ -392,7 +351,6 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { inputUnmarshalMap := graphql.BuildUnmarshalerMap( ec.unmarshalInputCreatePokemonInput, ec.unmarshalInputDeletePokemonInput, - ec.unmarshalInputLoginInput, ec.unmarshalInputUpdatePokemonInput, ) first := true @@ -454,20 +412,6 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ - {Name: "../schemas/authorization.graphqls", Input: `extend type Query { - login(input: LoginInput! ): LoginPayload -} - -input LoginInput { - username: String! - password: String! -} - -type LoginPayload { - success: Boolean! - message: String! - token: String! -}`, BuiltIn: false}, {Name: "../schemas/federation.graphqls", Input: ``, BuiltIn: false}, {Name: "../schemas/pokemon/create_pokemon.graphqls", Input: ` extend type Mutation { @@ -638,21 +582,6 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } -func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { - var err error - args := map[string]interface{}{} - var arg0 models.LoginInput - if tmp, ok := rawArgs["input"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginInput(ctx, tmp) - if err != nil { - return nil, err - } - } - args["input"] = arg0 - return args, nil -} - func (ec *executionContext) field_Query_pokemon_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -891,138 +820,6 @@ func (ec *executionContext) fieldContext_DeletePokemonPayload_success(ctx contex return fc, nil } -func (ec *executionContext) _LoginPayload_success(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_LoginPayload_success(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Success, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(bool) - fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_LoginPayload_success(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "LoginPayload", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Boolean does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _LoginPayload_message(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_LoginPayload_message(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Message, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_LoginPayload_message(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "LoginPayload", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - -func (ec *executionContext) _LoginPayload_token(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_LoginPayload_token(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return obj.Token, nil - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - if !graphql.HasFieldError(ctx, fc) { - ec.Errorf(ctx, "must not be null") - } - return graphql.Null - } - res := resTmp.(string) - fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_LoginPayload_token(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "LoginPayload", - Field: field, - IsMethod: false, - IsResolver: false, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") - }, - } - return fc, nil -} - func (ec *executionContext) _Mutation_createPokemon(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_createPokemon(ctx, field) if err != nil { @@ -1640,66 +1437,6 @@ func (ec *executionContext) fieldContext_PokemonType_slot(ctx context.Context, f return fc, nil } -func (ec *executionContext) _Query_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_login(ctx, field) - if err != nil { - return graphql.Null - } - ctx = graphql.WithFieldContext(ctx, fc) - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = graphql.Null - } - }() - resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { - ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Login(rctx, fc.Args["input"].(models.LoginInput)) - }) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - if resTmp == nil { - return graphql.Null - } - res := resTmp.(*models.LoginPayload) - fc.Result = res - return ec.marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginPayload(ctx, field.Selections, res) -} - -func (ec *executionContext) fieldContext_Query_login(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { - fc = &graphql.FieldContext{ - Object: "Query", - Field: field, - IsMethod: true, - IsResolver: true, - Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "success": - return ec.fieldContext_LoginPayload_success(ctx, field) - case "message": - return ec.fieldContext_LoginPayload_message(ctx, field) - case "token": - return ec.fieldContext_LoginPayload_token(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type LoginPayload", field.Name) - }, - } - defer func() { - if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) - } - }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_login_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { - ec.Error(ctx, err) - return - } - return fc, nil -} - func (ec *executionContext) _Query_pokemon(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_pokemon(ctx, field) if err != nil { @@ -4197,42 +3934,6 @@ func (ec *executionContext) unmarshalInputDeletePokemonInput(ctx context.Context return it, nil } -func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj interface{}) (models.LoginInput, error) { - var it models.LoginInput - asMap := map[string]interface{}{} - for k, v := range obj.(map[string]interface{}) { - asMap[k] = v - } - - fieldsInOrder := [...]string{"username", "password"} - for _, k := range fieldsInOrder { - v, ok := asMap[k] - if !ok { - continue - } - switch k { - case "username": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("username")) - it.Username, err = ec.unmarshalNString2string(ctx, v) - if err != nil { - return it, err - } - case "password": - var err error - - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) - it.Password, err = ec.unmarshalNString2string(ctx, v) - if err != nil { - return it, err - } - } - } - - return it, nil -} - func (ec *executionContext) unmarshalInputUpdatePokemonInput(ctx context.Context, obj interface{}) (models.UpdatePokemonInput, error) { var it models.UpdatePokemonInput asMap := map[string]interface{}{} @@ -4364,48 +4065,6 @@ func (ec *executionContext) _DeletePokemonPayload(ctx context.Context, sel ast.S return out } -var loginPayloadImplementors = []string{"LoginPayload"} - -func (ec *executionContext) _LoginPayload(ctx context.Context, sel ast.SelectionSet, obj *models.LoginPayload) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, loginPayloadImplementors) - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("LoginPayload") - case "success": - - out.Values[i] = ec._LoginPayload_success(ctx, field, obj) - - if out.Values[i] == graphql.Null { - invalids++ - } - case "message": - - out.Values[i] = ec._LoginPayload_message(ctx, field, obj) - - if out.Values[i] == graphql.Null { - invalids++ - } - case "token": - - out.Values[i] = ec._LoginPayload_token(ctx, field, obj) - - if out.Values[i] == graphql.Null { - invalids++ - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { - return graphql.Null - } - return out -} - var mutationImplementors = []string{"Mutation"} func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -4595,26 +4254,6 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") - case "login": - field := field - - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._Query_login(ctx, field) - return res - } - - rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) - } - - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) case "pokemon": field := field @@ -5196,11 +4835,6 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return res } -func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginInput(ctx context.Context, v interface{}) (models.LoginInput, error) { - res, err := ec.unmarshalInputLoginInput(ctx, v) - return res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -5559,13 +5193,6 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele return res } -func (ec *executionContext) marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginPayload(ctx context.Context, sel ast.SelectionSet, v *models.LoginPayload) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return ec._LoginPayload(ctx, sel, v) -} - func (ec *executionContext) marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v []*models.Pokemon) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/resolvers/authorization.resolvers.go b/graph/resolvers/authorization.resolvers.go deleted file mode 100644 index fcc131a..0000000 --- a/graph/resolvers/authorization.resolvers.go +++ /dev/null @@ -1,40 +0,0 @@ -package resolvers - -// This file will be automatically regenerated based on the schema, any resolver implementations -// will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. - -import ( - "context" - - "github.com/go-graphql/logger" - "github.com/sirupsen/logrus" - "github.com/vektah/gqlparser/gqlerror" - - "github.com/go-graphql/graph/generated" - "github.com/go-graphql/models" -) - -// Login is the resolver for the login field. -func (r *queryResolver) Login(ctx context.Context, input models.LoginInput) (*models.LoginPayload, error) { - token, err := r.AuthService.Login(ctx, input) - if err != nil { - logger.Log.WithFields(logrus.Fields{ - "error": err.Error(), - }).Error("Login") - return nil, gqlerror.Errorf(err.Error()) - } - - res := &models.LoginPayload{ - Success: true, - Message: "Login Success", - Token: token, - } - - return res, nil -} - -// Query returns generated.QueryResolver implementation. -func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } - -type queryResolver struct{ *Resolver } diff --git a/graph/resolvers/create_pokemon.resolvers.go b/graph/resolvers/create_pokemon.resolvers.go index e6adf83..8e44e7f 100644 --- a/graph/resolvers/create_pokemon.resolvers.go +++ b/graph/resolvers/create_pokemon.resolvers.go @@ -21,7 +21,7 @@ func (r *mutationResolver) CreatePokemon(ctx context.Context, input models.Creat if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/delete_pokemon.resolvers.go b/graph/resolvers/delete_pokemon.resolvers.go index 2a64aaa..a945d69 100644 --- a/graph/resolvers/delete_pokemon.resolvers.go +++ b/graph/resolvers/delete_pokemon.resolvers.go @@ -20,7 +20,7 @@ func (r *mutationResolver) DeletePokemon(ctx context.Context, input models.Delet if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/pokemon.resolvers.go b/graph/resolvers/pokemon.resolvers.go index fa4995f..9eb659a 100644 --- a/graph/resolvers/pokemon.resolvers.go +++ b/graph/resolvers/pokemon.resolvers.go @@ -22,7 +22,7 @@ func (r *pokemonResolver) Types(ctx context.Context, obj *models.Pokemon) ([]*mo if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } @@ -50,7 +50,7 @@ func (r *queryResolver) Pokemon(ctx context.Context, pokemonID int) (*models.Pok if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } @@ -70,4 +70,8 @@ func (r *queryResolver) Pokemon(ctx context.Context, pokemonID int) (*models.Pok // Pokemon returns generated.PokemonResolver implementation. func (r *Resolver) Pokemon() generated.PokemonResolver { return &pokemonResolver{r} } +// Query returns generated.QueryResolver implementation. +func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } + type pokemonResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } diff --git a/graph/resolvers/pokemons.resolvers.go b/graph/resolvers/pokemons.resolvers.go index 0a46b88..cf6c21b 100644 --- a/graph/resolvers/pokemons.resolvers.go +++ b/graph/resolvers/pokemons.resolvers.go @@ -21,7 +21,7 @@ func (r *queryResolver) Pokemons(ctx context.Context, limit *int, offset *int) ( if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/resolver.go b/graph/resolvers/resolver.go index 6210446..0a4150e 100644 --- a/graph/resolvers/resolver.go +++ b/graph/resolvers/resolver.go @@ -10,7 +10,6 @@ import ( // ResolverData - type ResolverData struct { - AuthService service.AuthServiceInterface PokemonService service.PokemonServiceInterface TypeService service.TypeServiceInterface // Other interfaces needed.... @@ -19,7 +18,6 @@ type ResolverData struct { // NewResolver - func NewResolver(data ResolverData) *Resolver { return &Resolver{ - AuthService: data.AuthService, PokemonService: data.PokemonService, TypeService: data.TypeService, } @@ -27,7 +25,6 @@ func NewResolver(data ResolverData) *Resolver { // Resolver - type Resolver struct { - AuthService service.AuthServiceInterface PokemonService service.PokemonServiceInterface TypeService service.TypeServiceInterface } diff --git a/graph/resolvers/types.resolvers.go b/graph/resolvers/types.resolvers.go index ea37bcf..4e3066a 100644 --- a/graph/resolvers/types.resolvers.go +++ b/graph/resolvers/types.resolvers.go @@ -21,7 +21,7 @@ func (r *queryResolver) Types(ctx context.Context, typeID *int) ([]*models.Type, if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/update_pokemon.resolvers.go b/graph/resolvers/update_pokemon.resolvers.go index eb09d45..4abb4a4 100644 --- a/graph/resolvers/update_pokemon.resolvers.go +++ b/graph/resolvers/update_pokemon.resolvers.go @@ -20,7 +20,7 @@ func (r *mutationResolver) UpdatePokemon(ctx context.Context, input models.Updat if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("User Authorization") + }).Error("ForContext") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/schemas/authorization.graphqls b/graph/schemas/authorization.graphqls deleted file mode 100644 index 09ee3d6..0000000 --- a/graph/schemas/authorization.graphqls +++ /dev/null @@ -1,14 +0,0 @@ -extend type Query { - login(input: LoginInput! ): LoginPayload -} - -input LoginInput { - username: String! - password: String! -} - -type LoginPayload { - success: Boolean! - message: String! - token: String! -} \ No newline at end of file diff --git a/models/models_gen.go b/models/models_gen.go index fb6f343..ac5426c 100644 --- a/models/models_gen.go +++ b/models/models_gen.go @@ -22,17 +22,6 @@ type DeletePokemonPayload struct { Success bool `json:"success"` } -type LoginInput struct { - Username string `json:"username"` - Password string `json:"password"` -} - -type LoginPayload struct { - Success bool `json:"success"` - Message string `json:"message"` - Token string `json:"token"` -} - type PokemonType struct { ID string `json:"id"` PokemonID int `json:"pokemonID"` diff --git a/server.go b/server.go index d6fc20f..7c63f49 100644 --- a/server.go +++ b/server.go @@ -21,8 +21,6 @@ func main() { typeRepo := repository.NewTypeRepository(db) // initialize service - authService := service.NewAuthService() - pokemonService := service.NewPokemonService(pokemonRepo) typeService := service.NewTypeService(typeRepo) @@ -30,7 +28,6 @@ func main() { resolverData := resolvers.ResolverData{ PokemonService: pokemonService, TypeService: typeService, - AuthService: authService, } resolver := resolvers.NewResolver(resolverData) diff --git a/service/auth.service.go b/service/auth.service.go deleted file mode 100644 index 81286f6..0000000 --- a/service/auth.service.go +++ /dev/null @@ -1,78 +0,0 @@ -package service - -import ( - "context" - "math/rand" - "os" - - "time" - - "github.com/go-graphql/auth" - "github.com/go-graphql/errors" - "github.com/go-graphql/models" - "github.com/golang-jwt/jwt" -) - -// AuthServiceInterface - . -type AuthServiceInterface interface { - Login(ctx context.Context, input models.LoginInput) (string, error) -} - -// AuthService - -type AuthService struct { - Issuer string - SecretKey string -} - -// NewAuthService - . -func NewAuthService() AuthServiceInterface { - return &AuthService{ - Issuer: os.Getenv("JWT_ISSUER"), - SecretKey: os.Getenv("JWT_SECRET_KEY"), - } -} - -// Login - login user -func (a *AuthService) Login(ctx context.Context, input models.LoginInput) (string, error) { - if input.Username != os.Getenv("LOGIN_USERNAME") || input.Password != os.Getenv("LOGIN_PASSWORD") { - return "", errors.ErrorAuth - } - - user := auth.User{ - UserID: rand.Intn(100), - Name: "Felix", - Username: input.Username, - IsAdmin: true, - } - - token, err := a.GenerateUserToken(user) - if err != nil { - return "", err - } - - return token, nil -} - -// GenerateUserToken - generate user jwt token. -func (a *AuthService) GenerateUserToken(user auth.User) (signedToken string, err error) { - expiredAt := time.Now().Local().Add(time.Hour * 1).Unix() - claims := &auth.JwtClaims{ - UserID: user.UserID, - Username: user.Username, - Name: user.Name, - IsAdmin: user.IsAdmin, - ExpiresAt: expiredAt, - StandardClaims: jwt.StandardClaims{ - ExpiresAt: expiredAt, - Issuer: a.Issuer, - }, - } - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - signedToken, err = token.SignedString([]byte(a.SecretKey)) - if err != nil { - return "", err - } - - return signedToken, nil -} From c35a3679d3e58124a614a0eb696c1534bfb7456f Mon Sep 17 00:00:00 2001 From: Felix Fernando Wijaya Date: Sat, 10 Dec 2022 17:53:52 +0700 Subject: [PATCH 2/5] Merge pull request #7 from voltgizerz/develop Develop --- .env.example | 6 +- README.md | 13 +- auth/jwt.go | 44 +++ auth/middleware.go | 30 +- errors/error.go | 13 +- go.mod | 1 + go.sum | 2 + graph/generated/generated.go | 373 ++++++++++++++++++++ graph/resolvers/authorization.resolvers.go | 40 +++ graph/resolvers/create_pokemon.resolvers.go | 2 +- graph/resolvers/delete_pokemon.resolvers.go | 2 +- graph/resolvers/pokemon.resolvers.go | 8 +- graph/resolvers/pokemons.resolvers.go | 2 +- graph/resolvers/resolver.go | 3 + graph/resolvers/types.resolvers.go | 2 +- graph/resolvers/update_pokemon.resolvers.go | 2 +- graph/schemas/authorization.graphqls | 14 + models/models_gen.go | 11 + server.go | 3 + service/auth.service.go | 78 ++++ 20 files changed, 617 insertions(+), 32 deletions(-) create mode 100644 auth/jwt.go create mode 100644 graph/resolvers/authorization.resolvers.go create mode 100644 graph/schemas/authorization.graphqls create mode 100644 service/auth.service.go diff --git a/.env.example b/.env.example index ba47f25..074c657 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,8 @@ DATA_SOURCE="your own db" DB_HOST_LOCAL= root:@tcp(localhost)/pokemon?charset=utf8mb4&parseTime=True&loc=Local ENV=development -GIN_MODE=debug \ No newline at end of file +GIN_MODE=debug +JWT_SECRET_KEY="secret" +JWT_ISSUER="jhon" +LOGIN_USERNAME="felix" +LOGIN_PASSWORD="felix" \ No newline at end of file diff --git a/README.md b/README.md index 3cfa4f1..f5f0f6c 100644 --- a/README.md +++ b/README.md @@ -51,12 +51,21 @@ make format ``` { - "user_id": 2323 + "Authorization":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzA2NzI0MjQsImlzcyI6Impob24iLCJVc2VySUQiOjgxLCJVc2VybmFtZSI6ImZlbGl4IiwiTmFtZSI6IkZlbGl4IiwiSXNBZG1pbiI6dHJ1ZSwiRXhwaXJlc0F0IjoxNjcwNjcyNDI0fQ.noKdYN3fhr7iwQmlDy1xYn1FqLsZ4gY-ORkWf3oeP_I" } ``` 💡 **Query** - +* Login get token +``` +query login { + login(input: {username: "felix", password: "felix"}) { + success + message + token + } +} +``` * Show all data pokemon (limit, offset, sort) ``` query pokemons { diff --git a/auth/jwt.go b/auth/jwt.go new file mode 100644 index 0000000..d560ac5 --- /dev/null +++ b/auth/jwt.go @@ -0,0 +1,44 @@ +package auth + +import ( + "errors" + "os" + "time" + + "github.com/golang-jwt/jwt" +) + +// JwtClaims - . +type JwtClaims struct { + jwt.StandardClaims + UserID int + Username string + Name string + IsAdmin bool + ExpiresAt int64 +} + +// ValidateAuthorization - validate jwt token. +func ValidateAuthorization(signedToken string) (claims *JwtClaims, err error) { + token, err := jwt.ParseWithClaims( + signedToken, + &JwtClaims{}, + func(token *jwt.Token) (interface{}, error) { + return []byte(os.Getenv("JWT_SECRET_KEY")), nil + }, + ) + if err != nil { + return + } + + claims, ok := token.Claims.(*JwtClaims) + if !ok { + return nil, errors.New("couldn't parse claims") + } + + if claims.StandardClaims.ExpiresAt < time.Now().Local().Unix() { + return nil, errors.New("jwt is expired") + } + + return claims, nil +} diff --git a/auth/middleware.go b/auth/middleware.go index 3b6e6d8..9031145 100644 --- a/auth/middleware.go +++ b/auth/middleware.go @@ -3,7 +3,6 @@ package auth import ( "context" "net/http" - "strconv" "github.com/go-graphql/errors" ) @@ -18,24 +17,27 @@ const ( // User - a stand-in for our database backed user object type User struct { - UserID int - Name string - IsAdmin bool + UserID int + Username string + Name string + IsAdmin bool } // Middleware - handle auth data func Middleware() func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - userID, err := strconv.Atoi(r.Header.Get("user_id")) - if err != nil { - userID = 0 // Default to 0 when header user_id not set - } - - user := &User{ - UserID: userID, - Name: "felix", - IsAdmin: true, + user := &User{} + authToken := r.Header.Get("authorization") + + if authToken != "" { + data, err := ValidateAuthorization(authToken) + if err == nil { + user.IsAdmin = data.IsAdmin + user.Name = data.Name + user.Username = data.Username + user.UserID = data.UserID + } } // put it in context @@ -52,7 +54,7 @@ func Middleware() func(http.Handler) http.Handler { func ForContext(ctx context.Context) (*User, error) { raw, _ := ctx.Value(CONTEXT_USER).(*User) if raw.UserID == 0 { - return nil, errors.ErrorHeaderNotSet + return nil, errors.ErrorNoAuthorization } return raw, nil diff --git a/errors/error.go b/errors/error.go index c5be62a..d8dc0d2 100644 --- a/errors/error.go +++ b/errors/error.go @@ -2,8 +2,13 @@ package errors import "errors" -// ErrorOccur - . -var ErrorOccur = errors.New("error") +var ( + // ErrorOccur - . + ErrorOccur = errors.New("error") -// ErrorHeaderNotSet - . -var ErrorHeaderNotSet = errors.New("header user_id is not set") + // ErrorNoAuthorization - . + ErrorNoAuthorization = errors.New("authorization is not valid") + + // ErrorAuth - . + ErrorAuth = errors.New("username or Password invalid") +) diff --git a/go.mod b/go.mod index 0fe1dfb..78f0f48 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/agnivade/levenshtein v1.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/mock v1.6.0 github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect diff --git a/go.sum b/go.sum index 4696365..f3369ad 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= diff --git a/graph/generated/generated.go b/graph/generated/generated.go index afbf67e..784476e 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -55,6 +55,12 @@ type ComplexityRoot struct { Success func(childComplexity int) int } + LoginPayload struct { + Message func(childComplexity int) int + Success func(childComplexity int) int + Token func(childComplexity int) int + } + Mutation struct { CreatePokemon func(childComplexity int, input models.CreatePokemonInput) int DeletePokemon func(childComplexity int, input models.DeletePokemonInput) int @@ -78,6 +84,7 @@ type ComplexityRoot struct { } Query struct { + Login func(childComplexity int, input models.LoginInput) int Pokemon func(childComplexity int, pokemonID int) int Pokemons func(childComplexity int, limit *int, offset *int) int Types func(childComplexity int, typeID *int) int @@ -109,6 +116,7 @@ type PokemonResolver interface { Types(ctx context.Context, obj *models.Pokemon) ([]*models.Type, error) } type QueryResolver interface { + Login(ctx context.Context, input models.LoginInput) (*models.LoginPayload, error) Pokemon(ctx context.Context, pokemonID int) (*models.Pokemon, error) Pokemons(ctx context.Context, limit *int, offset *int) ([]*models.Pokemon, error) Types(ctx context.Context, typeID *int) ([]*models.Type, error) @@ -150,6 +158,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DeletePokemonPayload.Success(childComplexity), true + case "LoginPayload.message": + if e.complexity.LoginPayload.Message == nil { + break + } + + return e.complexity.LoginPayload.Message(childComplexity), true + + case "LoginPayload.success": + if e.complexity.LoginPayload.Success == nil { + break + } + + return e.complexity.LoginPayload.Success(childComplexity), true + + case "LoginPayload.token": + if e.complexity.LoginPayload.Token == nil { + break + } + + return e.complexity.LoginPayload.Token(childComplexity), true + case "Mutation.createPokemon": if e.complexity.Mutation.CreatePokemon == nil { break @@ -256,6 +285,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.PokemonType.TypeID(childComplexity), true + case "Query.login": + if e.complexity.Query.Login == nil { + break + } + + args, err := ec.field_Query_login_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Login(childComplexity, args["input"].(models.LoginInput)), true + case "Query.pokemon": if e.complexity.Query.Pokemon == nil { break @@ -351,6 +392,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { inputUnmarshalMap := graphql.BuildUnmarshalerMap( ec.unmarshalInputCreatePokemonInput, ec.unmarshalInputDeletePokemonInput, + ec.unmarshalInputLoginInput, ec.unmarshalInputUpdatePokemonInput, ) first := true @@ -412,6 +454,20 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ + {Name: "../schemas/authorization.graphqls", Input: `extend type Query { + login(input: LoginInput! ): LoginPayload +} + +input LoginInput { + username: String! + password: String! +} + +type LoginPayload { + success: Boolean! + message: String! + token: String! +}`, BuiltIn: false}, {Name: "../schemas/federation.graphqls", Input: ``, BuiltIn: false}, {Name: "../schemas/pokemon/create_pokemon.graphqls", Input: ` extend type Mutation { @@ -582,6 +638,21 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 models.LoginInput + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_pokemon_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -820,6 +891,138 @@ func (ec *executionContext) fieldContext_DeletePokemonPayload_success(ctx contex return fc, nil } +func (ec *executionContext) _LoginPayload_success(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_LoginPayload_success(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Success, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_LoginPayload_success(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LoginPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _LoginPayload_message(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_LoginPayload_message(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Message, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_LoginPayload_message(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LoginPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _LoginPayload_token(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_LoginPayload_token(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Token, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_LoginPayload_token(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "LoginPayload", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _Mutation_createPokemon(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Mutation_createPokemon(ctx, field) if err != nil { @@ -1437,6 +1640,66 @@ func (ec *executionContext) fieldContext_PokemonType_slot(ctx context.Context, f return fc, nil } +func (ec *executionContext) _Query_login(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_login(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Login(rctx, fc.Args["input"].(models.LoginInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*models.LoginPayload) + fc.Result = res + return ec.marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginPayload(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_login(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "success": + return ec.fieldContext_LoginPayload_success(ctx, field) + case "message": + return ec.fieldContext_LoginPayload_message(ctx, field) + case "token": + return ec.fieldContext_LoginPayload_token(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type LoginPayload", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_login_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _Query_pokemon(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query_pokemon(ctx, field) if err != nil { @@ -3934,6 +4197,42 @@ func (ec *executionContext) unmarshalInputDeletePokemonInput(ctx context.Context return it, nil } +func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj interface{}) (models.LoginInput, error) { + var it models.LoginInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"username", "password"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "username": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("username")) + it.Username, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "password": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) + it.Password, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputUpdatePokemonInput(ctx context.Context, obj interface{}) (models.UpdatePokemonInput, error) { var it models.UpdatePokemonInput asMap := map[string]interface{}{} @@ -4065,6 +4364,48 @@ func (ec *executionContext) _DeletePokemonPayload(ctx context.Context, sel ast.S return out } +var loginPayloadImplementors = []string{"LoginPayload"} + +func (ec *executionContext) _LoginPayload(ctx context.Context, sel ast.SelectionSet, obj *models.LoginPayload) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, loginPayloadImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("LoginPayload") + case "success": + + out.Values[i] = ec._LoginPayload_success(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "message": + + out.Values[i] = ec._LoginPayload_message(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "token": + + out.Values[i] = ec._LoginPayload_token(ctx, field, obj) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var mutationImplementors = []string{"Mutation"} func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -4254,6 +4595,26 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Query") + case "login": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_login(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) case "pokemon": field := field @@ -4835,6 +5196,11 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return res } +func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginInput(ctx context.Context, v interface{}) (models.LoginInput, error) { + res, err := ec.unmarshalInputLoginInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -5193,6 +5559,13 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele return res } +func (ec *executionContext) marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginPayload(ctx context.Context, sel ast.SelectionSet, v *models.LoginPayload) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._LoginPayload(ctx, sel, v) +} + func (ec *executionContext) marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v []*models.Pokemon) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/resolvers/authorization.resolvers.go b/graph/resolvers/authorization.resolvers.go new file mode 100644 index 0000000..fcc131a --- /dev/null +++ b/graph/resolvers/authorization.resolvers.go @@ -0,0 +1,40 @@ +package resolvers + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. + +import ( + "context" + + "github.com/go-graphql/logger" + "github.com/sirupsen/logrus" + "github.com/vektah/gqlparser/gqlerror" + + "github.com/go-graphql/graph/generated" + "github.com/go-graphql/models" +) + +// Login is the resolver for the login field. +func (r *queryResolver) Login(ctx context.Context, input models.LoginInput) (*models.LoginPayload, error) { + token, err := r.AuthService.Login(ctx, input) + if err != nil { + logger.Log.WithFields(logrus.Fields{ + "error": err.Error(), + }).Error("Login") + return nil, gqlerror.Errorf(err.Error()) + } + + res := &models.LoginPayload{ + Success: true, + Message: "Login Success", + Token: token, + } + + return res, nil +} + +// Query returns generated.QueryResolver implementation. +func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } + +type queryResolver struct{ *Resolver } diff --git a/graph/resolvers/create_pokemon.resolvers.go b/graph/resolvers/create_pokemon.resolvers.go index 8e44e7f..e6adf83 100644 --- a/graph/resolvers/create_pokemon.resolvers.go +++ b/graph/resolvers/create_pokemon.resolvers.go @@ -21,7 +21,7 @@ func (r *mutationResolver) CreatePokemon(ctx context.Context, input models.Creat if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/delete_pokemon.resolvers.go b/graph/resolvers/delete_pokemon.resolvers.go index a945d69..2a64aaa 100644 --- a/graph/resolvers/delete_pokemon.resolvers.go +++ b/graph/resolvers/delete_pokemon.resolvers.go @@ -20,7 +20,7 @@ func (r *mutationResolver) DeletePokemon(ctx context.Context, input models.Delet if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/pokemon.resolvers.go b/graph/resolvers/pokemon.resolvers.go index 9eb659a..fa4995f 100644 --- a/graph/resolvers/pokemon.resolvers.go +++ b/graph/resolvers/pokemon.resolvers.go @@ -22,7 +22,7 @@ func (r *pokemonResolver) Types(ctx context.Context, obj *models.Pokemon) ([]*mo if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } @@ -50,7 +50,7 @@ func (r *queryResolver) Pokemon(ctx context.Context, pokemonID int) (*models.Pok if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } @@ -70,8 +70,4 @@ func (r *queryResolver) Pokemon(ctx context.Context, pokemonID int) (*models.Pok // Pokemon returns generated.PokemonResolver implementation. func (r *Resolver) Pokemon() generated.PokemonResolver { return &pokemonResolver{r} } -// Query returns generated.QueryResolver implementation. -func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} } - type pokemonResolver struct{ *Resolver } -type queryResolver struct{ *Resolver } diff --git a/graph/resolvers/pokemons.resolvers.go b/graph/resolvers/pokemons.resolvers.go index cf6c21b..0a46b88 100644 --- a/graph/resolvers/pokemons.resolvers.go +++ b/graph/resolvers/pokemons.resolvers.go @@ -21,7 +21,7 @@ func (r *queryResolver) Pokemons(ctx context.Context, limit *int, offset *int) ( if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/resolver.go b/graph/resolvers/resolver.go index 0a4150e..6210446 100644 --- a/graph/resolvers/resolver.go +++ b/graph/resolvers/resolver.go @@ -10,6 +10,7 @@ import ( // ResolverData - type ResolverData struct { + AuthService service.AuthServiceInterface PokemonService service.PokemonServiceInterface TypeService service.TypeServiceInterface // Other interfaces needed.... @@ -18,6 +19,7 @@ type ResolverData struct { // NewResolver - func NewResolver(data ResolverData) *Resolver { return &Resolver{ + AuthService: data.AuthService, PokemonService: data.PokemonService, TypeService: data.TypeService, } @@ -25,6 +27,7 @@ func NewResolver(data ResolverData) *Resolver { // Resolver - type Resolver struct { + AuthService service.AuthServiceInterface PokemonService service.PokemonServiceInterface TypeService service.TypeServiceInterface } diff --git a/graph/resolvers/types.resolvers.go b/graph/resolvers/types.resolvers.go index 4e3066a..ea37bcf 100644 --- a/graph/resolvers/types.resolvers.go +++ b/graph/resolvers/types.resolvers.go @@ -21,7 +21,7 @@ func (r *queryResolver) Types(ctx context.Context, typeID *int) ([]*models.Type, if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/resolvers/update_pokemon.resolvers.go b/graph/resolvers/update_pokemon.resolvers.go index 4abb4a4..eb09d45 100644 --- a/graph/resolvers/update_pokemon.resolvers.go +++ b/graph/resolvers/update_pokemon.resolvers.go @@ -20,7 +20,7 @@ func (r *mutationResolver) UpdatePokemon(ctx context.Context, input models.Updat if err != nil { logger.Log.WithFields(logrus.Fields{ "error": err.Error(), - }).Error("ForContext") + }).Error("User Authorization") return nil, gqlerror.Errorf(err.Error()) } diff --git a/graph/schemas/authorization.graphqls b/graph/schemas/authorization.graphqls new file mode 100644 index 0000000..09ee3d6 --- /dev/null +++ b/graph/schemas/authorization.graphqls @@ -0,0 +1,14 @@ +extend type Query { + login(input: LoginInput! ): LoginPayload +} + +input LoginInput { + username: String! + password: String! +} + +type LoginPayload { + success: Boolean! + message: String! + token: String! +} \ No newline at end of file diff --git a/models/models_gen.go b/models/models_gen.go index ac5426c..fb6f343 100644 --- a/models/models_gen.go +++ b/models/models_gen.go @@ -22,6 +22,17 @@ type DeletePokemonPayload struct { Success bool `json:"success"` } +type LoginInput struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type LoginPayload struct { + Success bool `json:"success"` + Message string `json:"message"` + Token string `json:"token"` +} + type PokemonType struct { ID string `json:"id"` PokemonID int `json:"pokemonID"` diff --git a/server.go b/server.go index 7c63f49..d6fc20f 100644 --- a/server.go +++ b/server.go @@ -21,6 +21,8 @@ func main() { typeRepo := repository.NewTypeRepository(db) // initialize service + authService := service.NewAuthService() + pokemonService := service.NewPokemonService(pokemonRepo) typeService := service.NewTypeService(typeRepo) @@ -28,6 +30,7 @@ func main() { resolverData := resolvers.ResolverData{ PokemonService: pokemonService, TypeService: typeService, + AuthService: authService, } resolver := resolvers.NewResolver(resolverData) diff --git a/service/auth.service.go b/service/auth.service.go new file mode 100644 index 0000000..81286f6 --- /dev/null +++ b/service/auth.service.go @@ -0,0 +1,78 @@ +package service + +import ( + "context" + "math/rand" + "os" + + "time" + + "github.com/go-graphql/auth" + "github.com/go-graphql/errors" + "github.com/go-graphql/models" + "github.com/golang-jwt/jwt" +) + +// AuthServiceInterface - . +type AuthServiceInterface interface { + Login(ctx context.Context, input models.LoginInput) (string, error) +} + +// AuthService - +type AuthService struct { + Issuer string + SecretKey string +} + +// NewAuthService - . +func NewAuthService() AuthServiceInterface { + return &AuthService{ + Issuer: os.Getenv("JWT_ISSUER"), + SecretKey: os.Getenv("JWT_SECRET_KEY"), + } +} + +// Login - login user +func (a *AuthService) Login(ctx context.Context, input models.LoginInput) (string, error) { + if input.Username != os.Getenv("LOGIN_USERNAME") || input.Password != os.Getenv("LOGIN_PASSWORD") { + return "", errors.ErrorAuth + } + + user := auth.User{ + UserID: rand.Intn(100), + Name: "Felix", + Username: input.Username, + IsAdmin: true, + } + + token, err := a.GenerateUserToken(user) + if err != nil { + return "", err + } + + return token, nil +} + +// GenerateUserToken - generate user jwt token. +func (a *AuthService) GenerateUserToken(user auth.User) (signedToken string, err error) { + expiredAt := time.Now().Local().Add(time.Hour * 1).Unix() + claims := &auth.JwtClaims{ + UserID: user.UserID, + Username: user.Username, + Name: user.Name, + IsAdmin: user.IsAdmin, + ExpiresAt: expiredAt, + StandardClaims: jwt.StandardClaims{ + ExpiresAt: expiredAt, + Issuer: a.Issuer, + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + signedToken, err = token.SignedString([]byte(a.SecretKey)) + if err != nil { + return "", err + } + + return signedToken, nil +} From fbb31907cc6f86351ffc11e2ed9f5775523b06ca Mon Sep 17 00:00:00 2001 From: voltgizerz Date: Sun, 8 Jan 2023 01:08:45 +0700 Subject: [PATCH 3/5] Add federation schema user --- config/gqlgen.go | 2 +- graph/generated/federation.go | 152 ++++++++ graph/generated/generated.go | 395 ++++++++++++++++++++- graph/resolvers/authorization.resolvers.go | 5 +- graph/resolvers/entity.resolvers.go | 47 +++ graph/schemas/pokemon/pokemon.graphqls | 2 +- models/pokemon.go | 2 + 7 files changed, 598 insertions(+), 7 deletions(-) create mode 100644 graph/resolvers/entity.resolvers.go diff --git a/config/gqlgen.go b/config/gqlgen.go index 4c02460..b83900f 100644 --- a/config/gqlgen.go +++ b/config/gqlgen.go @@ -45,7 +45,7 @@ func InitGQL(srv *handler.Server) { logger.Log.Infof("connect to http://localhost:%s/ for GraphQL playground", port) - err := http.ListenAndServe(":"+port, router) + err := http.ListenAndServe("127.0.0.1:"+port, router) if err != nil { logger.Log.Fatal(err) } diff --git a/graph/generated/federation.go b/graph/generated/federation.go index 1116a02..8fd3120 100644 --- a/graph/generated/federation.go +++ b/graph/generated/federation.go @@ -5,7 +5,9 @@ package generated import ( "context" "errors" + "fmt" "strings" + "sync" "github.com/99designs/gqlgen/plugin/federation/fedruntime" ) @@ -33,3 +35,153 @@ func (ec *executionContext) __resolve__service(ctx context.Context) (fedruntime. SDL: strings.Join(sdl, "\n"), }, nil } + +func (ec *executionContext) __resolve_entities(ctx context.Context, representations []map[string]interface{}) []fedruntime.Entity { + list := make([]fedruntime.Entity, len(representations)) + + repsMap := map[string]struct { + i []int + r []map[string]interface{} + }{} + + // We group entities by typename so that we can parallelize their resolution. + // This is particularly helpful when there are entity groups in multi mode. + buildRepresentationGroups := func(reps []map[string]interface{}) { + for i, rep := range reps { + typeName, ok := rep["__typename"].(string) + if !ok { + // If there is no __typename, we just skip the representation; + // we just won't be resolving these unknown types. + ec.Error(ctx, errors.New("__typename must be an existing string")) + continue + } + + _r := repsMap[typeName] + _r.i = append(_r.i, i) + _r.r = append(_r.r, rep) + repsMap[typeName] = _r + } + } + + isMulti := func(typeName string) bool { + switch typeName { + default: + return false + } + } + + resolveEntity := func(ctx context.Context, typeName string, rep map[string]interface{}, idx []int, i int) (err error) { + // we need to do our own panic handling, because we may be called in a + // goroutine, where the usual panic handling can't catch us + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + } + }() + + switch typeName { + case "Pokemon": + resolverName, err := entityResolverNameForPokemon(ctx, rep) + if err != nil { + return fmt.Errorf(`finding resolver for Entity "Pokemon": %w`, err) + } + switch resolverName { + + case "findPokemonByID": + id0, err := ec.unmarshalNID2string(ctx, rep["id"]) + if err != nil { + return fmt.Errorf(`unmarshalling param 0 for findPokemonByID(): %w`, err) + } + entity, err := ec.resolvers.Entity().FindPokemonByID(ctx, id0) + if err != nil { + return fmt.Errorf(`resolving Entity "Pokemon": %w`, err) + } + + list[idx[i]] = entity + return nil + } + + } + return fmt.Errorf("%w: %s", ErrUnknownType, typeName) + } + + resolveManyEntities := func(ctx context.Context, typeName string, reps []map[string]interface{}, idx []int) (err error) { + // we need to do our own panic handling, because we may be called in a + // goroutine, where the usual panic handling can't catch us + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + } + }() + + switch typeName { + + default: + return errors.New("unknown type: " + typeName) + } + } + + resolveEntityGroup := func(typeName string, reps []map[string]interface{}, idx []int) { + if isMulti(typeName) { + err := resolveManyEntities(ctx, typeName, reps, idx) + if err != nil { + ec.Error(ctx, err) + } + } else { + // if there are multiple entities to resolve, parallelize (similar to + // graphql.FieldSet.Dispatch) + var e sync.WaitGroup + e.Add(len(reps)) + for i, rep := range reps { + i, rep := i, rep + go func(i int, rep map[string]interface{}) { + err := resolveEntity(ctx, typeName, rep, idx, i) + if err != nil { + ec.Error(ctx, err) + } + e.Done() + }(i, rep) + } + e.Wait() + } + } + buildRepresentationGroups(representations) + + switch len(repsMap) { + case 0: + return list + case 1: + for typeName, reps := range repsMap { + resolveEntityGroup(typeName, reps.r, reps.i) + } + return list + default: + var g sync.WaitGroup + g.Add(len(repsMap)) + for typeName, reps := range repsMap { + go func(typeName string, reps []map[string]interface{}, idx []int) { + resolveEntityGroup(typeName, reps, idx) + g.Done() + }(typeName, reps.r, reps.i) + } + g.Wait() + return list + } +} + +func entityResolverNameForPokemon(ctx context.Context, rep map[string]interface{}) (string, error) { + for { + var ( + m map[string]interface{} + val interface{} + ok bool + ) + _ = val + m = rep + if _, ok = m["id"]; !ok { + break + } + return "findPokemonByID", nil + } + return "", fmt.Errorf("%w for Pokemon", ErrTypeNotFound) +} diff --git a/graph/generated/generated.go b/graph/generated/generated.go index 784476e..028c91b 100644 --- a/graph/generated/generated.go +++ b/graph/generated/generated.go @@ -37,6 +37,7 @@ type Config struct { } type ResolverRoot interface { + Entity() EntityResolver Mutation() MutationResolver Pokemon() PokemonResolver Query() QueryResolver @@ -55,6 +56,10 @@ type ComplexityRoot struct { Success func(childComplexity int) int } + Entity struct { + FindPokemonByID func(childComplexity int, id string) int + } + LoginPayload struct { Message func(childComplexity int) int Success func(childComplexity int) int @@ -89,6 +94,7 @@ type ComplexityRoot struct { Pokemons func(childComplexity int, limit *int, offset *int) int Types func(childComplexity int, typeID *int) int __resolve__service func(childComplexity int) int + __resolve_entities func(childComplexity int, representations []map[string]interface{}) int } Type struct { @@ -107,6 +113,9 @@ type ComplexityRoot struct { } } +type EntityResolver interface { + FindPokemonByID(ctx context.Context, id string) (*models.Pokemon, error) +} type MutationResolver interface { CreatePokemon(ctx context.Context, input models.CreatePokemonInput) (*models.CreatePokemonPayload, error) DeletePokemon(ctx context.Context, input models.DeletePokemonInput) (*models.DeletePokemonPayload, error) @@ -158,6 +167,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DeletePokemonPayload.Success(childComplexity), true + case "Entity.findPokemonByID": + if e.complexity.Entity.FindPokemonByID == nil { + break + } + + args, err := ec.field_Entity_findPokemonByID_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Entity.FindPokemonByID(childComplexity, args["id"].(string)), true + case "LoginPayload.message": if e.complexity.LoginPayload.Message == nil { break @@ -340,6 +361,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.__resolve__service(childComplexity), true + case "Query._entities": + if e.complexity.Query.__resolve_entities == nil { + break + } + + args, err := ec.field_Query__entities_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.__resolve_entities(childComplexity, args["representations"].([]map[string]interface{})), true + case "Type.damageTypeID": if e.complexity.Type.DamageTypeID == nil { break @@ -501,7 +534,7 @@ type DeletePokemonPayload { pokemon(pokemonID: Int!): Pokemon } -type Pokemon { +type Pokemon @key(fields: "id") { id: ID! name: String! height: Int! @@ -563,11 +596,21 @@ type Type { directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE `, BuiltIn: true}, {Name: "../../federation/entity.graphql", Input: ` +# a union of all types that use the @key directive +union _Entity = Pokemon + +# fake type to build resolver interfaces for users to implement +type Entity { + findPokemonByID(id: ID!,): Pokemon! + +} + type _Service { sdl: String } extend type Query { + _entities(representations: [_Any!]!): [_Entity]! _service: _Service! } `, BuiltIn: true}, @@ -578,6 +621,21 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** +func (ec *executionContext) field_Entity_findPokemonByID_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 string + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_createPokemon_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -638,6 +696,21 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs return args, nil } +func (ec *executionContext) field_Query__entities_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 []map[string]interface{} + if tmp, ok := rawArgs["representations"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("representations")) + arg0, err = ec.unmarshalN_Any2ᚕmapᚄ(ctx, tmp) + if err != nil { + return nil, err + } + } + args["representations"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -891,6 +964,75 @@ func (ec *executionContext) fieldContext_DeletePokemonPayload_success(ctx contex return fc, nil } +func (ec *executionContext) _Entity_findPokemonByID(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Entity_findPokemonByID(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Entity().FindPokemonByID(rctx, fc.Args["id"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*models.Pokemon) + fc.Result = res + return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Entity_findPokemonByID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Entity", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Pokemon_id(ctx, field) + case "name": + return ec.fieldContext_Pokemon_name(ctx, field) + case "height": + return ec.fieldContext_Pokemon_height(ctx, field) + case "weight": + return ec.fieldContext_Pokemon_weight(ctx, field) + case "baseExperience": + return ec.fieldContext_Pokemon_baseExperience(ctx, field) + case "types": + return ec.fieldContext_Pokemon_types(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Pokemon", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Entity_findPokemonByID_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _LoginPayload_success(ctx context.Context, field graphql.CollectedField, obj *models.LoginPayload) (ret graphql.Marshaler) { fc, err := ec.fieldContext_LoginPayload_success(ctx, field) if err != nil { @@ -1892,6 +2034,61 @@ func (ec *executionContext) fieldContext_Query_types(ctx context.Context, field return fc, nil } +func (ec *executionContext) _Query__entities(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query__entities(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.__resolve_entities(ctx, fc.Args["representations"].([]map[string]interface{})), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]fedruntime.Entity) + fc.Result = res + return ec.marshalN_Entity2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋfedruntimeᚐEntity(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query__entities(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type _Entity does not have child fields") + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query__entities_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return + } + return fc, nil +} + func (ec *executionContext) _Query__service(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Query__service(ctx, field) if err != nil { @@ -4297,6 +4494,22 @@ func (ec *executionContext) unmarshalInputUpdatePokemonInput(ctx context.Context // region ************************** interface.gotpl *************************** +func (ec *executionContext) __Entity(ctx context.Context, sel ast.SelectionSet, obj fedruntime.Entity) graphql.Marshaler { + switch obj := (obj).(type) { + case nil: + return graphql.Null + case models.Pokemon: + return ec._Pokemon(ctx, sel, &obj) + case *models.Pokemon: + if obj == nil { + return graphql.Null + } + return ec._Pokemon(ctx, sel, obj) + default: + panic(fmt.Errorf("unexpected type %T", obj)) + } +} + // endregion ************************** interface.gotpl *************************** // region **************************** object.gotpl **************************** @@ -4364,6 +4577,59 @@ func (ec *executionContext) _DeletePokemonPayload(ctx context.Context, sel ast.S return out } +var entityImplementors = []string{"Entity"} + +func (ec *executionContext) _Entity(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, entityImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Entity", + }) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Entity") + case "findPokemonByID": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Entity_findPokemonByID(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var loginPayloadImplementors = []string{"LoginPayload"} func (ec *executionContext) _LoginPayload(ctx context.Context, sel ast.SelectionSet, obj *models.LoginPayload) graphql.Marshaler { @@ -4454,7 +4720,7 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) return out } -var pokemonImplementors = []string{"Pokemon"} +var pokemonImplementors = []string{"Pokemon", "_Entity"} func (ec *executionContext) _Pokemon(ctx context.Context, sel ast.SelectionSet, obj *models.Pokemon) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, pokemonImplementors) @@ -4672,6 +4938,29 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) } + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "_entities": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query__entities(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + out.Concurrently(i, func() graphql.Marshaler { return rrm(innerCtx) }) @@ -5201,6 +5490,10 @@ func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋm return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNPokemon2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v models.Pokemon) graphql.Marshaler { + return ec._Pokemon(ctx, sel, &v) +} + func (ec *executionContext) marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { @@ -5231,6 +5524,97 @@ func (ec *executionContext) unmarshalNUpdatePokemonInput2githubᚗcomᚋgoᚑgra return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalN_Any2map(ctx context.Context, v interface{}) (map[string]interface{}, error) { + res, err := graphql.UnmarshalMap(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN_Any2map(ctx context.Context, sel ast.SelectionSet, v map[string]interface{}) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + res := graphql.MarshalMap(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalN_Any2ᚕmapᚄ(ctx context.Context, v interface{}) ([]map[string]interface{}, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]map[string]interface{}, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN_Any2map(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN_Any2ᚕmapᚄ(ctx context.Context, sel ast.SelectionSet, v []map[string]interface{}) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalN_Any2map(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN_Entity2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋfedruntimeᚐEntity(ctx context.Context, sel ast.SelectionSet, v []fedruntime.Entity) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalO_Entity2githubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋfedruntimeᚐEntity(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + func (ec *executionContext) unmarshalN_FieldSet2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.ErrorOnPath(ctx, err) @@ -5695,6 +6079,13 @@ func (ec *executionContext) marshalOUpdatePokemonPayload2ᚖgithubᚗcomᚋgoᚑ return ec._UpdatePokemonPayload(ctx, sel, v) } +func (ec *executionContext) marshalO_Entity2githubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋfedruntimeᚐEntity(ctx context.Context, sel ast.SelectionSet, v fedruntime.Entity) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.__Entity(ctx, sel, v) +} + func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/graph/resolvers/authorization.resolvers.go b/graph/resolvers/authorization.resolvers.go index fcc131a..c599032 100644 --- a/graph/resolvers/authorization.resolvers.go +++ b/graph/resolvers/authorization.resolvers.go @@ -7,12 +7,11 @@ package resolvers import ( "context" + "github.com/go-graphql/graph/generated" "github.com/go-graphql/logger" + "github.com/go-graphql/models" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" - - "github.com/go-graphql/graph/generated" - "github.com/go-graphql/models" ) // Login is the resolver for the login field. diff --git a/graph/resolvers/entity.resolvers.go b/graph/resolvers/entity.resolvers.go new file mode 100644 index 0000000..5a3f53c --- /dev/null +++ b/graph/resolvers/entity.resolvers.go @@ -0,0 +1,47 @@ +package resolvers + +// This file will be automatically regenerated based on the schema, any resolver implementations +// will be copied through when generating and any unknown code will be moved to the end. +// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. + +import ( + "context" + "strconv" + + "github.com/go-graphql/graph/generated" + "github.com/go-graphql/models" + "github.com/vektah/gqlparser/gqlerror" +) + +// FindPokemonByID is the resolver for the findPokemonByID field. +func (r *entityResolver) FindPokemonByID(ctx context.Context, id string) (*models.Pokemon, error) { + // user, err := auth.ForContext(ctx) + // if err != nil { + // logger.Log.WithFields(logrus.Fields{ + // "error": err.Error(), + // }).Error("User Authorization") + // return nil, gqlerror.Errorf(err.Error()) + // } + + // logger.Log.WithFields(logrus.Fields{ + // "user_id": user.UserID, + // "is_admin": user.IsAdmin, + // }).Info("entityResolver FindPokemonByID") + + pokemonID, err := strconv.Atoi(id) + if err != nil { + return nil, gqlerror.Errorf(err.Error()) + } + + res, err := r.Resolver.PokemonService.FetchOne(ctx, pokemonID) + if err != nil { + return nil, gqlerror.Errorf(err.Error()) + } + + return res, nil +} + +// Entity returns generated.EntityResolver implementation. +func (r *Resolver) Entity() generated.EntityResolver { return &entityResolver{r} } + +type entityResolver struct{ *Resolver } diff --git a/graph/schemas/pokemon/pokemon.graphqls b/graph/schemas/pokemon/pokemon.graphqls index 01b67c2..2bfce94 100644 --- a/graph/schemas/pokemon/pokemon.graphqls +++ b/graph/schemas/pokemon/pokemon.graphqls @@ -2,7 +2,7 @@ extend type Query { pokemon(pokemonID: Int!): Pokemon } -type Pokemon { +type Pokemon @key(fields: "id") { id: ID! name: String! height: Int! diff --git a/models/pokemon.go b/models/pokemon.go index 342bae4..beacf1f 100644 --- a/models/pokemon.go +++ b/models/pokemon.go @@ -9,3 +9,5 @@ type Pokemon struct { BaseExperience int `json:"baseExperience"` Types []*Type `json:"types"` } + +func (Pokemon) IsEntity() {} From 084a51eeb88dc8b89c1db8fa9f56a8444e0db976 Mon Sep 17 00:00:00 2001 From: voltgizerz Date: Sun, 8 Jan 2023 21:42:22 +0700 Subject: [PATCH 4/5] Add logic goroutine to handle interrupt and stopped --- config/gqlgen.go | 2 +- server.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/config/gqlgen.go b/config/gqlgen.go index b83900f..f01650f 100644 --- a/config/gqlgen.go +++ b/config/gqlgen.go @@ -16,7 +16,7 @@ import ( ) // defaultPort - running port -const defaultPort = "8080" +const defaultPort = "8086" // InitGQL - init gqlgen func InitGQL(srv *handler.Server) { diff --git a/server.go b/server.go index d6fc20f..1f3274c 100644 --- a/server.go +++ b/server.go @@ -1,7 +1,12 @@ package main import ( + "os" + "os/signal" + "syscall" + "github.com/go-graphql/config" + "github.com/go-graphql/logger" "github.com/go-graphql/repository" "github.com/go-graphql/service" @@ -10,7 +15,23 @@ import ( "github.com/go-graphql/graph/resolvers" ) +// Set up a goroutine that will run the signal handler. +// This goroutine will block until a signal is received. +func handleSignal(c chan os.Signal) { + s := <-c + logger.Log.Warn("got signal: ", s) + + os.Exit(0) +} + func main() { + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTSTP) + + // Set up a goroutine that will run the signal handler. + // This goroutine will block until a signal is received. + go handleSignal(c) + config.LoadENV() // initialize database From 5b0e9cb10ba7a4d19c824f9f263ccad989fe9bff Mon Sep 17 00:00:00 2001 From: voltgizerz Date: Sun, 9 Jul 2023 21:02:02 +0700 Subject: [PATCH 5/5] Refactor code --- Makefile | 4 +- Dockerfile => build/Dockerfile | 0 server.go => cmd/server.go | 11 +- config/database.go | 1 + config/gqlgen.go | 2 +- go.mod | 20 +- go.sum | 82 +- gqlgen.yml | 14 +- {auth => internal/app/auth}/jwt.go | 0 {auth => internal/app/auth}/middleware.go | 2 +- .../app/dataloader}/loaders.go | 0 .../app}/dumps/pokemon_types.sql | 0 {database => internal/app}/dumps/pokemons.sql | 0 {database => internal/app}/dumps/types.sql | 0 {errors => internal/app/errors}/error.go | 0 .../app/graph}/generated/federation.go | 0 .../app/graph}/generated/generated.go | 802 +++++++++++------- .../resolvers/authorization.resolvers.go | 6 +- .../resolvers/create_pokemon.resolvers.go | 8 +- .../create_pokemon.resolvers_test.go | 10 +- .../resolvers/delete_pokemon.resolvers.go | 6 +- .../app/graph}/resolvers/entity.resolvers.go | 6 +- .../app/graph}/resolvers/pokemon.resolvers.go | 8 +- .../graph}/resolvers/pokemons.resolvers.go | 8 +- .../app/graph}/resolvers/resolver.go | 2 +- .../app/graph}/resolvers/types.resolvers.go | 8 +- .../resolvers/update_pokemon.resolvers.go | 6 +- .../app/graph}/schemas/authorization.graphqls | 0 .../app/graph}/schemas/federation.graphqls | 0 .../schemas/pokemon/create_pokemon.graphqls | 0 .../schemas/pokemon/delete_pokemon.graphqls | 0 .../graph}/schemas/pokemon/pokemon.graphqls | 0 .../graph}/schemas/pokemon/pokemons.graphqls | 0 .../schemas/pokemon/update_pokemon.graphqls | 0 .../pokemon_types/pokemon_type.graphqls | 0 .../app/graph}/schemas/scalars.graphqls | 0 .../app/graph}/schemas/type/types.graphqls | 0 .../app/mocks}/mock_PokemonService.go | 2 +- .../app/mocks}/mock_TypeService.go | 2 +- {models => internal/app/models}/models_gen.go | 14 +- {models => internal/app/models}/pokemon.go | 7 + .../app/repository}/pokemon.repository.go | 2 +- .../app/repository}/type.repository.go | 2 +- .../app/service}/auth.service.go | 6 +- .../app/service}/pokemon.service.go | 4 +- .../app/service}/type.service.go | 4 +- {utils => internal/app/utils}/utils.go | 0 {utils => internal/app/utils}/utils_test.go | 0 logger/logger.go | 15 +- 49 files changed, 597 insertions(+), 467 deletions(-) rename Dockerfile => build/Dockerfile (100%) rename server.go => cmd/server.go (84%) rename {auth => internal/app/auth}/jwt.go (100%) rename {auth => internal/app/auth}/middleware.go (96%) rename {dataloader => internal/app/dataloader}/loaders.go (100%) rename {database => internal/app}/dumps/pokemon_types.sql (100%) rename {database => internal/app}/dumps/pokemons.sql (100%) rename {database => internal/app}/dumps/types.sql (100%) rename {errors => internal/app/errors}/error.go (100%) rename {graph => internal/app/graph}/generated/federation.go (100%) rename {graph => internal/app/graph}/generated/generated.go (92%) rename {graph => internal/app/graph}/resolvers/authorization.resolvers.go (85%) rename {graph => internal/app/graph}/resolvers/create_pokemon.resolvers.go (85%) rename {graph => internal/app/graph}/resolvers/create_pokemon.resolvers_test.go (88%) rename {graph => internal/app/graph}/resolvers/delete_pokemon.resolvers.go (87%) rename {graph => internal/app/graph}/resolvers/entity.resolvers.go (88%) rename {graph => internal/app/graph}/resolvers/pokemon.resolvers.go (89%) rename {graph => internal/app/graph}/resolvers/pokemons.resolvers.go (83%) rename {graph => internal/app/graph}/resolvers/resolver.go (94%) rename {graph => internal/app/graph}/resolvers/types.resolvers.go (82%) rename {graph => internal/app/graph}/resolvers/update_pokemon.resolvers.go (85%) rename {graph => internal/app/graph}/schemas/authorization.graphqls (100%) rename {graph => internal/app/graph}/schemas/federation.graphqls (100%) rename {graph => internal/app/graph}/schemas/pokemon/create_pokemon.graphqls (100%) rename {graph => internal/app/graph}/schemas/pokemon/delete_pokemon.graphqls (100%) rename {graph => internal/app/graph}/schemas/pokemon/pokemon.graphqls (100%) rename {graph => internal/app/graph}/schemas/pokemon/pokemons.graphqls (100%) rename {graph => internal/app/graph}/schemas/pokemon/update_pokemon.graphqls (100%) rename {graph => internal/app/graph}/schemas/pokemon_types/pokemon_type.graphqls (100%) rename {graph => internal/app/graph}/schemas/scalars.graphqls (100%) rename {graph => internal/app/graph}/schemas/type/types.graphqls (100%) rename {mocks => internal/app/mocks}/mock_PokemonService.go (98%) rename {mocks => internal/app/mocks}/mock_TypeService.go (97%) rename {models => internal/app/models}/models_gen.go (78%) rename {models => internal/app/models}/pokemon.go (69%) rename {repository => internal/app/repository}/pokemon.repository.go (98%) rename {repository => internal/app/repository}/type.repository.go (97%) rename {service => internal/app/service}/auth.service.go (92%) rename {service => internal/app/service}/pokemon.service.go (94%) rename {service => internal/app/service}/type.service.go (90%) rename {utils => internal/app/utils}/utils.go (100%) rename {utils => internal/app/utils}/utils_test.go (100%) diff --git a/Makefile b/Makefile index 423ecb6..67b386f 100644 --- a/Makefile +++ b/Makefile @@ -3,14 +3,14 @@ format: gr: go run github.com/99designs/gqlgen generate - go run server.go + go run ./cmd/server.go generate: go run github.com/99designs/gqlgen generate run: gofmt -w ./.. - go run server.go + go run ./cmd/server.go test: go test -v -cover ./... diff --git a/Dockerfile b/build/Dockerfile similarity index 100% rename from Dockerfile rename to build/Dockerfile diff --git a/server.go b/cmd/server.go similarity index 84% rename from server.go rename to cmd/server.go index 1f3274c..94b180c 100644 --- a/server.go +++ b/cmd/server.go @@ -3,16 +3,15 @@ package main import ( "os" "os/signal" - "syscall" "github.com/go-graphql/config" + "github.com/go-graphql/internal/app/repository" + "github.com/go-graphql/internal/app/service" "github.com/go-graphql/logger" - "github.com/go-graphql/repository" - "github.com/go-graphql/service" "github.com/99designs/gqlgen/graphql/handler" - "github.com/go-graphql/graph/generated" - "github.com/go-graphql/graph/resolvers" + "github.com/go-graphql/internal/app/graph/generated" + "github.com/go-graphql/internal/app/graph/resolvers" ) // Set up a goroutine that will run the signal handler. @@ -26,7 +25,7 @@ func handleSignal(c chan os.Signal) { func main() { c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTSTP) + signal.Notify(c, os.Interrupt) // Set up a goroutine that will run the signal handler. // This goroutine will block until a signal is received. diff --git a/config/database.go b/config/database.go index 8ca05e1..cdfd06c 100644 --- a/config/database.go +++ b/config/database.go @@ -21,6 +21,7 @@ func InitDB() *Database { db, err := sql.Open("mysql", os.Getenv("DATA_SOURCE")) if err != nil { logger.Log.Println(errors.Wrap(err, "database connection")) + panic(err) } db.SetMaxOpenConns(10) diff --git a/config/gqlgen.go b/config/gqlgen.go index f01650f..825e134 100644 --- a/config/gqlgen.go +++ b/config/gqlgen.go @@ -9,7 +9,7 @@ import ( "github.com/99designs/gqlgen/graphql/playground" "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" - "github.com/go-graphql/auth" + "github.com/go-graphql/internal/app/auth" "github.com/go-graphql/logger" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" diff --git a/go.mod b/go.mod index 78f0f48..04e51f8 100644 --- a/go.mod +++ b/go.mod @@ -4,17 +4,20 @@ module github.com/go-graphql go 1.19 require ( - github.com/99designs/gqlgen v0.17.21 + github.com/99designs/gqlgen v0.17.34 + github.com/antonfisher/nested-logrus-formatter v1.3.1 github.com/go-chi/chi v1.5.4 github.com/go-sql-driver/mysql v1.6.0 github.com/joho/godotenv v1.4.0 github.com/pkg/errors v0.9.1 github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.8.2 github.com/vektah/gqlparser v1.3.1 - github.com/vektah/gqlparser/v2 v2.5.1 + github.com/vektah/gqlparser/v2 v2.5.4 ) +require github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect + require ( github.com/agnivade/levenshtein v1.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect @@ -22,15 +25,14 @@ require ( github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/mock v1.6.0 github.com/gorilla/websocket v1.5.0 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/urfave/cli/v2 v2.23.5 // indirect + github.com/urfave/cli/v2 v2.25.5 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/sys v0.2.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/tools v0.3.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.9.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f3369ad..dac8a67 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,14 @@ -github.com/99designs/gqlgen v0.17.21 h1:JCFyw3RdXwQlQCq6To5Z/KNaGDJigQt43eLvtqhH0yE= -github.com/99designs/gqlgen v0.17.21/go.mod h1:BMhYIhe4bp7OlCo5I2PnowSK/Wimpv/YlxfNkqZGwLo= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/99designs/gqlgen v0.17.34 h1:5cS5/OKFguQt+Ws56uj9FlG2xm1IlcJWNF2jrMIKYFQ= +github.com/99designs/gqlgen v0.17.34/go.mod h1:Axcd3jIFHBVcqzixujJQr1wGqE+lGTpz6u4iZBZg1G8= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ= +github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -24,24 +24,17 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE= +github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kevinmbeaulieu/eq-go v1.0.0/go.mod h1:G3S8ajA56gKBZm4UB9AOyoOS37JO3roToPzKNM8dtdM= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= -github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -51,89 +44,66 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.8.1/go.mod h1:Z41J9TPoffeoqP0Iza0YbAhGvymRdZAd2uPmZ5JxRdY= -github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw= -github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc= +github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/vektah/gqlparser v1.3.1 h1:8b0IcD3qZKWJQHSzynbDlrtP3IxVydZ2DZepCGofqfU= github.com/vektah/gqlparser v1.3.1/go.mod h1:bkVf0FX+Stjg/MHnm8mEyubuaArhNEqfQhF+OTiAL74= -github.com/vektah/gqlparser/v2 v2.5.1 h1:ZGu+bquAY23jsxDRcYpWjttRZrUz07LbiY77gUOHcr4= -github.com/vektah/gqlparser/v2 v2.5.1/go.mod h1:mPgqFBu/woKTVYWyNk8cO3kh4S/f4aRFZrvOnp3hmCs= +github.com/vektah/gqlparser/v2 v2.5.4 h1:TKZYLje269xipIHcoHPR0eRE40ONGjEXrbiN2SvurgY= +github.com/vektah/gqlparser/v2 v2.5.4/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gqlgen.yml b/gqlgen.yml index 2591dce..87eeba7 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -1,26 +1,26 @@ # Where are all the schema files located? globs are supported eg src/**/*.graphqls schema: - - graph/schemas/**/*.graphqls + - internal/app/graph/schemas/**/*.graphqls # Where should the generated server code go? exec: - filename: graph/generated/generated.go + filename: internal/app/graph/generated/generated.go package: generated # Uncomment to enable federation federation: - filename: graph/generated/federation.go + filename: internal/app/graph/generated/federation.go package: generated # Where should any generated models go? model: - filename: models/models_gen.go + filename: internal/app/models/models_gen.go package: models # Where should the resolver implementations go? resolver: layout: follow-schema - dir: graph/resolvers + dir: internal/app/graph/resolvers package: resolvers # Optional: turn on use `gqlgen:"fieldName"` tags in your models @@ -35,7 +35,7 @@ resolver: # gqlgen will search for any type names in the schema in these go packages # if they match it will use them, otherwise it will generate them. autobind: - - "github.com/go-graphql/models" + - "github.com/go-graphql/internal/app/models" # This section declares type mapping between the GraphQL and go type systems # @@ -56,7 +56,7 @@ models: - github.com/99designs/gqlgen/graphql.Int32 Pokemon: model: - - github.com/go-graphql/models.Pokemon + - github.com/go-graphql/internal/app/models.Pokemon fields: types: resolver: true \ No newline at end of file diff --git a/auth/jwt.go b/internal/app/auth/jwt.go similarity index 100% rename from auth/jwt.go rename to internal/app/auth/jwt.go diff --git a/auth/middleware.go b/internal/app/auth/middleware.go similarity index 96% rename from auth/middleware.go rename to internal/app/auth/middleware.go index 9031145..ef5b85f 100644 --- a/auth/middleware.go +++ b/internal/app/auth/middleware.go @@ -4,7 +4,7 @@ import ( "context" "net/http" - "github.com/go-graphql/errors" + "github.com/go-graphql/internal/app/errors" ) type contextKey string diff --git a/dataloader/loaders.go b/internal/app/dataloader/loaders.go similarity index 100% rename from dataloader/loaders.go rename to internal/app/dataloader/loaders.go diff --git a/database/dumps/pokemon_types.sql b/internal/app/dumps/pokemon_types.sql similarity index 100% rename from database/dumps/pokemon_types.sql rename to internal/app/dumps/pokemon_types.sql diff --git a/database/dumps/pokemons.sql b/internal/app/dumps/pokemons.sql similarity index 100% rename from database/dumps/pokemons.sql rename to internal/app/dumps/pokemons.sql diff --git a/database/dumps/types.sql b/internal/app/dumps/types.sql similarity index 100% rename from database/dumps/types.sql rename to internal/app/dumps/types.sql diff --git a/errors/error.go b/internal/app/errors/error.go similarity index 100% rename from errors/error.go rename to internal/app/errors/error.go diff --git a/graph/generated/federation.go b/internal/app/graph/generated/federation.go similarity index 100% rename from graph/generated/federation.go rename to internal/app/graph/generated/federation.go diff --git a/graph/generated/generated.go b/internal/app/graph/generated/generated.go similarity index 92% rename from graph/generated/generated.go rename to internal/app/graph/generated/generated.go index 028c91b..757fc68 100644 --- a/graph/generated/generated.go +++ b/internal/app/graph/generated/generated.go @@ -14,7 +14,7 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" "github.com/99designs/gqlgen/plugin/federation/fedruntime" - "github.com/go-graphql/models" + "github.com/go-graphql/internal/app/models" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" ) @@ -142,7 +142,7 @@ func (e *executableSchema) Schema() *ast.Schema { } func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) { - ec := executionContext{nil, e} + ec := executionContext{nil, e, 0, 0, nil} _ = ec switch typeName + "." + field { @@ -421,7 +421,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { rc := graphql.GetOperationContext(ctx) - ec := executionContext{rc, e} + ec := executionContext{rc, e, 0, 0, make(chan graphql.DeferredResult)} inputUnmarshalMap := graphql.BuildUnmarshalerMap( ec.unmarshalInputCreatePokemonInput, ec.unmarshalInputDeletePokemonInput, @@ -433,18 +433,33 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { switch rc.Operation.Operation { case ast.Query: return func(ctx context.Context) *graphql.Response { - if !first { - return nil + var response graphql.Response + var data graphql.Marshaler + if first { + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data = ec._Query(ctx, rc.Operation.SelectionSet) + } else { + if atomic.LoadInt32(&ec.pendingDeferred) > 0 { + result := <-ec.deferredResults + atomic.AddInt32(&ec.pendingDeferred, -1) + data = result.Result + response.Path = result.Path + response.Label = result.Label + response.Errors = result.Errors + } else { + return nil + } } - first = false - ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) - data := ec._Query(ctx, rc.Operation.SelectionSet) var buf bytes.Buffer data.MarshalGQL(&buf) - - return &graphql.Response{ - Data: buf.Bytes(), + response.Data = buf.Bytes() + if atomic.LoadInt32(&ec.deferred) > 0 { + hasNext := atomic.LoadInt32(&ec.pendingDeferred) > 0 + response.HasNext = &hasNext } + + return &response } case ast.Mutation: return func(ctx context.Context) *graphql.Response { @@ -470,6 +485,28 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { type executionContext struct { *graphql.OperationContext *executableSchema + deferred int32 + pendingDeferred int32 + deferredResults chan graphql.DeferredResult +} + +func (ec *executionContext) processDeferredGroup(dg graphql.DeferredGroup) { + atomic.AddInt32(&ec.pendingDeferred, 1) + go func() { + ctx := graphql.WithFreshResponseContext(dg.Context) + dg.FieldSet.Dispatch(ctx) + ds := graphql.DeferredResult{ + Path: dg.Path, + Label: dg.Label, + Result: dg.FieldSet, + Errors: graphql.GetErrors(ctx), + } + // null fields should bubble up + if dg.FieldSet.Invalids > 0 { + ds.Result = graphql.Null + } + ec.deferredResults <- ds + }() } func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { @@ -584,18 +621,16 @@ type Type { damageTypeID: Int! } `, BuiltIn: false}, - {Name: "../../federation/directives.graphql", Input: ` - scalar _Any - scalar _FieldSet - - directive @external on FIELD_DEFINITION + {Name: "../../../../federation/directives.graphql", Input: ` + directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE directive @requires(fields: _FieldSet!) on FIELD_DEFINITION directive @provides(fields: _FieldSet!) on FIELD_DEFINITION directive @extends on OBJECT | INTERFACE - - directive @key(fields: _FieldSet!) repeatable on OBJECT | INTERFACE + directive @external on FIELD_DEFINITION + scalar _Any + scalar _FieldSet `, BuiltIn: true}, - {Name: "../../federation/entity.graphql", Input: ` + {Name: "../../../../federation/entity.graphql", Input: ` # a union of all types that use the @key directive union _Entity = Pokemon @@ -642,7 +677,7 @@ func (ec *executionContext) field_Mutation_createPokemon_args(ctx context.Contex var arg0 models.CreatePokemonInput if tmp, ok := rawArgs["input"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNCreatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐCreatePokemonInput(ctx, tmp) + arg0, err = ec.unmarshalNCreatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐCreatePokemonInput(ctx, tmp) if err != nil { return nil, err } @@ -657,7 +692,7 @@ func (ec *executionContext) field_Mutation_deletePokemon_args(ctx context.Contex var arg0 models.DeletePokemonInput if tmp, ok := rawArgs["input"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNDeletePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐDeletePokemonInput(ctx, tmp) + arg0, err = ec.unmarshalNDeletePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐDeletePokemonInput(ctx, tmp) if err != nil { return nil, err } @@ -672,7 +707,7 @@ func (ec *executionContext) field_Mutation_updatePokemon_args(ctx context.Contex var arg0 models.UpdatePokemonInput if tmp, ok := rawArgs["input"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNUpdatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐUpdatePokemonInput(ctx, tmp) + arg0, err = ec.unmarshalNUpdatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐUpdatePokemonInput(ctx, tmp) if err != nil { return nil, err } @@ -717,7 +752,7 @@ func (ec *executionContext) field_Query_login_args(ctx context.Context, rawArgs var arg0 models.LoginInput if tmp, ok := rawArgs["input"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) - arg0, err = ec.unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginInput(ctx, tmp) + arg0, err = ec.unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐLoginInput(ctx, tmp) if err != nil { return nil, err } @@ -890,7 +925,7 @@ func (ec *executionContext) _CreatePokemonPayload_pokemon(ctx context.Context, f } res := resTmp.(*models.Pokemon) fc.Result = res - return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, field.Selections, res) + return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_CreatePokemonPayload_pokemon(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -992,7 +1027,7 @@ func (ec *executionContext) _Entity_findPokemonByID(ctx context.Context, field g } res := resTmp.(*models.Pokemon) fc.Result = res - return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, field.Selections, res) + return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Entity_findPokemonByID(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1028,7 +1063,7 @@ func (ec *executionContext) fieldContext_Entity_findPokemonByID(ctx context.Cont ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Entity_findPokemonByID_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1190,7 +1225,7 @@ func (ec *executionContext) _Mutation_createPokemon(ctx context.Context, field g } res := resTmp.(*models.CreatePokemonPayload) fc.Result = res - return ec.marshalOCreatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐCreatePokemonPayload(ctx, field.Selections, res) + return ec.marshalOCreatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐCreatePokemonPayload(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Mutation_createPokemon(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1218,7 +1253,7 @@ func (ec *executionContext) fieldContext_Mutation_createPokemon(ctx context.Cont ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Mutation_createPokemon_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1248,7 +1283,7 @@ func (ec *executionContext) _Mutation_deletePokemon(ctx context.Context, field g } res := resTmp.(*models.DeletePokemonPayload) fc.Result = res - return ec.marshalODeletePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐDeletePokemonPayload(ctx, field.Selections, res) + return ec.marshalODeletePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐDeletePokemonPayload(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Mutation_deletePokemon(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1274,7 +1309,7 @@ func (ec *executionContext) fieldContext_Mutation_deletePokemon(ctx context.Cont ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Mutation_deletePokemon_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1304,7 +1339,7 @@ func (ec *executionContext) _Mutation_updatePokemon(ctx context.Context, field g } res := resTmp.(*models.UpdatePokemonPayload) fc.Result = res - return ec.marshalOUpdatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐUpdatePokemonPayload(ctx, field.Selections, res) + return ec.marshalOUpdatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐUpdatePokemonPayload(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Mutation_updatePokemon(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1332,7 +1367,7 @@ func (ec *executionContext) fieldContext_Mutation_updatePokemon(ctx context.Cont ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Mutation_updatePokemon_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1582,7 +1617,7 @@ func (ec *executionContext) _Pokemon_types(ctx context.Context, field graphql.Co } res := resTmp.([]*models.Type) fc.Result = res - return ec.marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐType(ctx, field.Selections, res) + return ec.marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐType(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Pokemon_types(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1807,7 +1842,7 @@ func (ec *executionContext) _Query_login(ctx context.Context, field graphql.Coll } res := resTmp.(*models.LoginPayload) fc.Result = res - return ec.marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginPayload(ctx, field.Selections, res) + return ec.marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐLoginPayload(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_login(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1837,7 +1872,7 @@ func (ec *executionContext) fieldContext_Query_login(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Query_login_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1867,7 +1902,7 @@ func (ec *executionContext) _Query_pokemon(ctx context.Context, field graphql.Co } res := resTmp.(*models.Pokemon) fc.Result = res - return ec.marshalOPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, field.Selections, res) + return ec.marshalOPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_pokemon(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1903,7 +1938,7 @@ func (ec *executionContext) fieldContext_Query_pokemon(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Query_pokemon_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1933,7 +1968,7 @@ func (ec *executionContext) _Query_pokemons(ctx context.Context, field graphql.C } res := resTmp.([]*models.Pokemon) fc.Result = res - return ec.marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, field.Selections, res) + return ec.marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_pokemons(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -1969,7 +2004,7 @@ func (ec *executionContext) fieldContext_Query_pokemons(ctx context.Context, fie ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Query_pokemons_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -1999,7 +2034,7 @@ func (ec *executionContext) _Query_types(ctx context.Context, field graphql.Coll } res := resTmp.([]*models.Type) fc.Result = res - return ec.marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐType(ctx, field.Selections, res) + return ec.marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐType(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_Query_types(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -2029,7 +2064,7 @@ func (ec *executionContext) fieldContext_Query_types(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Query_types_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -2084,7 +2119,7 @@ func (ec *executionContext) fieldContext_Query__entities(ctx context.Context, fi ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Query__entities_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -2206,7 +2241,7 @@ func (ec *executionContext) fieldContext_Query___type(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field_Query___type_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -2470,7 +2505,7 @@ func (ec *executionContext) _UpdatePokemonPayload_pokemon(ctx context.Context, f } res := resTmp.(*models.Pokemon) fc.Result = res - return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, field.Selections, res) + return ec.marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx, field.Selections, res) } func (ec *executionContext) fieldContext_UpdatePokemonPayload_pokemon(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { @@ -3962,7 +3997,7 @@ func (ec *executionContext) fieldContext___Type_fields(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field___Type_fields_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -4150,7 +4185,7 @@ func (ec *executionContext) fieldContext___Type_enumValues(ctx context.Context, ctx = graphql.WithFieldContext(ctx, fc) if fc.Args, err = ec.field___Type_enumValues_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { ec.Error(ctx, err) - return + return fc, err } return fc, nil } @@ -4332,34 +4367,38 @@ func (ec *executionContext) unmarshalInputCreatePokemonInput(ctx context.Context var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - it.Name, err = ec.unmarshalNString2string(ctx, v) + data, err := ec.unmarshalNString2string(ctx, v) if err != nil { return it, err } + it.Name = data case "height": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("height")) - it.Height, err = ec.unmarshalNInt2int(ctx, v) + data, err := ec.unmarshalNInt2int(ctx, v) if err != nil { return it, err } + it.Height = data case "weight": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("weight")) - it.Weight, err = ec.unmarshalNInt2int(ctx, v) + data, err := ec.unmarshalNInt2int(ctx, v) if err != nil { return it, err } + it.Weight = data case "baseExperience": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("baseExperience")) - it.BaseExperience, err = ec.unmarshalNInt2int(ctx, v) + data, err := ec.unmarshalNInt2int(ctx, v) if err != nil { return it, err } + it.BaseExperience = data } } @@ -4384,10 +4423,11 @@ func (ec *executionContext) unmarshalInputDeletePokemonInput(ctx context.Context var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - it.ID, err = ec.unmarshalNInt2int(ctx, v) + data, err := ec.unmarshalNInt2int(ctx, v) if err != nil { return it, err } + it.ID = data } } @@ -4412,18 +4452,20 @@ func (ec *executionContext) unmarshalInputLoginInput(ctx context.Context, obj in var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("username")) - it.Username, err = ec.unmarshalNString2string(ctx, v) + data, err := ec.unmarshalNString2string(ctx, v) if err != nil { return it, err } + it.Username = data case "password": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("password")) - it.Password, err = ec.unmarshalNString2string(ctx, v) + data, err := ec.unmarshalNString2string(ctx, v) if err != nil { return it, err } + it.Password = data } } @@ -4448,42 +4490,47 @@ func (ec *executionContext) unmarshalInputUpdatePokemonInput(ctx context.Context var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - it.ID, err = ec.unmarshalNInt2int(ctx, v) + data, err := ec.unmarshalNInt2int(ctx, v) if err != nil { return it, err } + it.ID = data case "name": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - it.Name, err = ec.unmarshalOString2ᚖstring(ctx, v) + data, err := ec.unmarshalOString2ᚖstring(ctx, v) if err != nil { return it, err } + it.Name = data case "height": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("height")) - it.Height, err = ec.unmarshalOInt2ᚖint(ctx, v) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } + it.Height = data case "weight": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("weight")) - it.Weight, err = ec.unmarshalOInt2ᚖint(ctx, v) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } + it.Weight = data case "baseExperience": var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("baseExperience")) - it.BaseExperience, err = ec.unmarshalOInt2ᚖint(ctx, v) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) if err != nil { return it, err } + it.BaseExperience = data } } @@ -4518,34 +4565,43 @@ var createPokemonPayloadImplementors = []string{"CreatePokemonPayload"} func (ec *executionContext) _CreatePokemonPayload(ctx context.Context, sel ast.SelectionSet, obj *models.CreatePokemonPayload) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, createPokemonPayloadImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("CreatePokemonPayload") case "success": - out.Values[i] = ec._CreatePokemonPayload_success(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "pokemon": - out.Values[i] = ec._CreatePokemonPayload_pokemon(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4553,27 +4609,38 @@ var deletePokemonPayloadImplementors = []string{"DeletePokemonPayload"} func (ec *executionContext) _DeletePokemonPayload(ctx context.Context, sel ast.SelectionSet, obj *models.DeletePokemonPayload) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, deletePokemonPayloadImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("DeletePokemonPayload") case "success": - out.Values[i] = ec._DeletePokemonPayload_success(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4586,7 +4653,7 @@ func (ec *executionContext) _Entity(ctx context.Context, sel ast.SelectionSet) g }) out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ Object: field.Name, @@ -4599,7 +4666,7 @@ func (ec *executionContext) _Entity(ctx context.Context, sel ast.SelectionSet) g case "findPokemonByID": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4607,26 +4674,37 @@ func (ec *executionContext) _Entity(ctx context.Context, sel ast.SelectionSet) g }() res = ec._Entity_findPokemonByID(ctx, field) if res == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&fs.Invalids, 1) } return res } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4634,41 +4712,48 @@ var loginPayloadImplementors = []string{"LoginPayload"} func (ec *executionContext) _LoginPayload(ctx context.Context, sel ast.SelectionSet, obj *models.LoginPayload) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, loginPayloadImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("LoginPayload") case "success": - out.Values[i] = ec._LoginPayload_success(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "message": - out.Values[i] = ec._LoginPayload_message(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "token": - out.Values[i] = ec._LoginPayload_token(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4681,7 +4766,7 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) }) out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ Object: field.Name, @@ -4692,31 +4777,37 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) case "__typename": out.Values[i] = graphql.MarshalString("Mutation") case "createPokemon": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_createPokemon(ctx, field) }) - case "deletePokemon": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_deletePokemon(ctx, field) }) - case "updatePokemon": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Mutation_updatePokemon(ctx, field) }) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4724,51 +4815,42 @@ var pokemonImplementors = []string{"Pokemon", "_Entity"} func (ec *executionContext) _Pokemon(ctx context.Context, sel ast.SelectionSet, obj *models.Pokemon) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, pokemonImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Pokemon") case "id": - out.Values[i] = ec._Pokemon_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&out.Invalids, 1) } case "name": - out.Values[i] = ec._Pokemon_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&out.Invalids, 1) } case "height": - out.Values[i] = ec._Pokemon_height(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&out.Invalids, 1) } case "weight": - out.Values[i] = ec._Pokemon_weight(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&out.Invalids, 1) } case "baseExperience": - out.Values[i] = ec._Pokemon_baseExperience(ctx, field, obj) - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&out.Invalids, 1) } case "types": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4778,18 +4860,46 @@ func (ec *executionContext) _Pokemon(ctx context.Context, sel ast.SelectionSet, return res } - out.Concurrently(i, func() graphql.Marshaler { - return innerFunc(ctx) + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4797,48 +4907,53 @@ var pokemonTypeImplementors = []string{"PokemonType"} func (ec *executionContext) _PokemonType(ctx context.Context, sel ast.SelectionSet, obj *models.PokemonType) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, pokemonTypeImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("PokemonType") case "id": - out.Values[i] = ec._PokemonType_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "pokemonID": - out.Values[i] = ec._PokemonType_pokemonID(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "typeID": - out.Values[i] = ec._PokemonType_typeID(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "slot": - out.Values[i] = ec._PokemonType_slot(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -4851,7 +4966,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr }) out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ Object: field.Name, @@ -4864,7 +4979,7 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr case "login": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4875,16 +4990,15 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "pokemon": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4895,16 +5009,15 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "pokemons": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4915,16 +5028,15 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "types": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4935,16 +5047,15 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "_entities": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4952,22 +5063,21 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr }() res = ec._Query__entities(ctx, field) if res == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&fs.Invalids, 1) } return res } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "_service": field := field - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -4975,38 +5085,45 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr }() res = ec._Query__service(ctx, field) if res == graphql.Null { - atomic.AddUint32(&invalids, 1) + atomic.AddUint32(&fs.Invalids, 1) } return res } rrm := func(ctx context.Context) graphql.Marshaler { - return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) } - out.Concurrently(i, func() graphql.Marshaler { - return rrm(innerCtx) - }) + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) }) case "__type": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Query___type(ctx, field) }) - case "__schema": - out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { return ec._Query___schema(ctx, field) }) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5014,41 +5131,48 @@ var typeImplementors = []string{"Type"} func (ec *executionContext) _Type(ctx context.Context, sel ast.SelectionSet, obj *models.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, typeImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("Type") case "id": - out.Values[i] = ec._Type_id(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "name": - out.Values[i] = ec._Type_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "damageTypeID": - out.Values[i] = ec._Type_damageTypeID(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5056,34 +5180,43 @@ var updatePokemonPayloadImplementors = []string{"UpdatePokemonPayload"} func (ec *executionContext) _UpdatePokemonPayload(ctx context.Context, sel ast.SelectionSet, obj *models.UpdatePokemonPayload) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, updatePokemonPayloadImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("UpdatePokemonPayload") case "success": - out.Values[i] = ec._UpdatePokemonPayload_success(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "pokemon": - out.Values[i] = ec._UpdatePokemonPayload_pokemon(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5091,24 +5224,35 @@ var _ServiceImplementors = []string{"_Service"} func (ec *executionContext) __Service(ctx context.Context, sel ast.SelectionSet, obj *fedruntime.Service) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, _ServiceImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("_Service") case "sdl": - out.Values[i] = ec.__Service_sdl(ctx, field, obj) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5116,52 +5260,55 @@ var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __DirectiveImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Directive") case "name": - out.Values[i] = ec.___Directive_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "description": - out.Values[i] = ec.___Directive_description(ctx, field, obj) - case "locations": - out.Values[i] = ec.___Directive_locations(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "args": - out.Values[i] = ec.___Directive_args(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "isRepeatable": - out.Values[i] = ec.___Directive_isRepeatable(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5169,42 +5316,47 @@ var __EnumValueImplementors = []string{"__EnumValue"} func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__EnumValue") case "name": - out.Values[i] = ec.___EnumValue_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "description": - out.Values[i] = ec.___EnumValue_description(ctx, field, obj) - case "isDeprecated": - out.Values[i] = ec.___EnumValue_isDeprecated(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "deprecationReason": - out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5212,56 +5364,57 @@ var __FieldImplementors = []string{"__Field"} func (ec *executionContext) ___Field(ctx context.Context, sel ast.SelectionSet, obj *introspection.Field) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __FieldImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Field") case "name": - out.Values[i] = ec.___Field_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "description": - out.Values[i] = ec.___Field_description(ctx, field, obj) - case "args": - out.Values[i] = ec.___Field_args(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "type": - out.Values[i] = ec.___Field_type(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "isDeprecated": - out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "deprecationReason": - out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5269,42 +5422,47 @@ var __InputValueImplementors = []string{"__InputValue"} func (ec *executionContext) ___InputValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.InputValue) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __InputValueImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__InputValue") case "name": - out.Values[i] = ec.___InputValue_name(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "description": - out.Values[i] = ec.___InputValue_description(ctx, field, obj) - case "type": - out.Values[i] = ec.___InputValue_type(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "defaultValue": - out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5312,53 +5470,54 @@ var __SchemaImplementors = []string{"__Schema"} func (ec *executionContext) ___Schema(ctx context.Context, sel ast.SelectionSet, obj *introspection.Schema) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __SchemaImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Schema") case "description": - out.Values[i] = ec.___Schema_description(ctx, field, obj) - case "types": - out.Values[i] = ec.___Schema_types(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "queryType": - out.Values[i] = ec.___Schema_queryType(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "mutationType": - out.Values[i] = ec.___Schema_mutationType(ctx, field, obj) - case "subscriptionType": - out.Values[i] = ec.___Schema_subscriptionType(ctx, field, obj) - case "directives": - out.Values[i] = ec.___Schema_directives(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5366,63 +5525,56 @@ var __TypeImplementors = []string{"__Type"} func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) + out := graphql.NewFieldSet(fields) - var invalids uint32 + deferred := make(map[string]*graphql.FieldSet) for i, field := range fields { switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("__Type") case "kind": - out.Values[i] = ec.___Type_kind(ctx, field, obj) - if out.Values[i] == graphql.Null { - invalids++ + out.Invalids++ } case "name": - out.Values[i] = ec.___Type_name(ctx, field, obj) - case "description": - out.Values[i] = ec.___Type_description(ctx, field, obj) - case "fields": - out.Values[i] = ec.___Type_fields(ctx, field, obj) - case "interfaces": - out.Values[i] = ec.___Type_interfaces(ctx, field, obj) - case "possibleTypes": - out.Values[i] = ec.___Type_possibleTypes(ctx, field, obj) - case "enumValues": - out.Values[i] = ec.___Type_enumValues(ctx, field, obj) - case "inputFields": - out.Values[i] = ec.___Type_inputFields(ctx, field, obj) - case "ofType": - out.Values[i] = ec.___Type_ofType(ctx, field, obj) - case "specifiedByURL": - out.Values[i] = ec.___Type_specifiedByURL(ctx, field, obj) - default: panic("unknown field " + strconv.Quote(field.Name)) } } - out.Dispatch() - if invalids > 0 { + out.Dispatch(ctx) + if out.Invalids > 0 { return graphql.Null } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + return out } @@ -5445,12 +5597,12 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } -func (ec *executionContext) unmarshalNCreatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐCreatePokemonInput(ctx context.Context, v interface{}) (models.CreatePokemonInput, error) { +func (ec *executionContext) unmarshalNCreatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐCreatePokemonInput(ctx context.Context, v interface{}) (models.CreatePokemonInput, error) { res, err := ec.unmarshalInputCreatePokemonInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalNDeletePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐDeletePokemonInput(ctx context.Context, v interface{}) (models.DeletePokemonInput, error) { +func (ec *executionContext) unmarshalNDeletePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐDeletePokemonInput(ctx context.Context, v interface{}) (models.DeletePokemonInput, error) { res, err := ec.unmarshalInputDeletePokemonInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) } @@ -5485,16 +5637,16 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return res } -func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginInput(ctx context.Context, v interface{}) (models.LoginInput, error) { +func (ec *executionContext) unmarshalNLoginInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐLoginInput(ctx context.Context, v interface{}) (models.LoginInput, error) { res, err := ec.unmarshalInputLoginInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNPokemon2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v models.Pokemon) graphql.Marshaler { +func (ec *executionContext) marshalNPokemon2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v models.Pokemon) graphql.Marshaler { return ec._Pokemon(ctx, sel, &v) } -func (ec *executionContext) marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { +func (ec *executionContext) marshalNPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "the requested element is null which the schema does not allow") @@ -5519,7 +5671,7 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S return res } -func (ec *executionContext) unmarshalNUpdatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋmodelsᚐUpdatePokemonInput(ctx context.Context, v interface{}) (models.UpdatePokemonInput, error) { +func (ec *executionContext) unmarshalNUpdatePokemonInput2githubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐUpdatePokemonInput(ctx context.Context, v interface{}) (models.UpdatePokemonInput, error) { res, err := ec.unmarshalInputUpdatePokemonInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) } @@ -5913,14 +6065,14 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return res } -func (ec *executionContext) marshalOCreatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐCreatePokemonPayload(ctx context.Context, sel ast.SelectionSet, v *models.CreatePokemonPayload) graphql.Marshaler { +func (ec *executionContext) marshalOCreatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐCreatePokemonPayload(ctx context.Context, sel ast.SelectionSet, v *models.CreatePokemonPayload) graphql.Marshaler { if v == nil { return graphql.Null } return ec._CreatePokemonPayload(ctx, sel, v) } -func (ec *executionContext) marshalODeletePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐDeletePokemonPayload(ctx context.Context, sel ast.SelectionSet, v *models.DeletePokemonPayload) graphql.Marshaler { +func (ec *executionContext) marshalODeletePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐDeletePokemonPayload(ctx context.Context, sel ast.SelectionSet, v *models.DeletePokemonPayload) graphql.Marshaler { if v == nil { return graphql.Null } @@ -5943,14 +6095,14 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele return res } -func (ec *executionContext) marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐLoginPayload(ctx context.Context, sel ast.SelectionSet, v *models.LoginPayload) graphql.Marshaler { +func (ec *executionContext) marshalOLoginPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐLoginPayload(ctx context.Context, sel ast.SelectionSet, v *models.LoginPayload) graphql.Marshaler { if v == nil { return graphql.Null } return ec._LoginPayload(ctx, sel, v) } -func (ec *executionContext) marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v []*models.Pokemon) graphql.Marshaler { +func (ec *executionContext) marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v []*models.Pokemon) graphql.Marshaler { if v == nil { return graphql.Null } @@ -5977,7 +6129,7 @@ func (ec *executionContext) marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋ if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalOPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx, sel, v[i]) + ret[i] = ec.marshalOPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx, sel, v[i]) } if isLen1 { f(i) @@ -5991,7 +6143,7 @@ func (ec *executionContext) marshalOPokemon2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋ return ret } -func (ec *executionContext) marshalOPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { +func (ec *executionContext) marshalOPokemon2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐPokemon(ctx context.Context, sel ast.SelectionSet, v *models.Pokemon) graphql.Marshaler { if v == nil { return graphql.Null } @@ -6024,7 +6176,7 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as return res } -func (ec *executionContext) marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐType(ctx context.Context, sel ast.SelectionSet, v []*models.Type) graphql.Marshaler { +func (ec *executionContext) marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐType(ctx context.Context, sel ast.SelectionSet, v []*models.Type) graphql.Marshaler { if v == nil { return graphql.Null } @@ -6051,7 +6203,7 @@ func (ec *executionContext) marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmod if !isLen1 { defer wg.Done() } - ret[i] = ec.marshalOType2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐType(ctx, sel, v[i]) + ret[i] = ec.marshalOType2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐType(ctx, sel, v[i]) } if isLen1 { f(i) @@ -6065,14 +6217,14 @@ func (ec *executionContext) marshalOType2ᚕᚖgithubᚗcomᚋgoᚑgraphqlᚋmod return ret } -func (ec *executionContext) marshalOType2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐType(ctx context.Context, sel ast.SelectionSet, v *models.Type) graphql.Marshaler { +func (ec *executionContext) marshalOType2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐType(ctx context.Context, sel ast.SelectionSet, v *models.Type) graphql.Marshaler { if v == nil { return graphql.Null } return ec._Type(ctx, sel, v) } -func (ec *executionContext) marshalOUpdatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋmodelsᚐUpdatePokemonPayload(ctx context.Context, sel ast.SelectionSet, v *models.UpdatePokemonPayload) graphql.Marshaler { +func (ec *executionContext) marshalOUpdatePokemonPayload2ᚖgithubᚗcomᚋgoᚑgraphqlᚋinternalᚋappᚋmodelsᚐUpdatePokemonPayload(ctx context.Context, sel ast.SelectionSet, v *models.UpdatePokemonPayload) graphql.Marshaler { if v == nil { return graphql.Null } diff --git a/graph/resolvers/authorization.resolvers.go b/internal/app/graph/resolvers/authorization.resolvers.go similarity index 85% rename from graph/resolvers/authorization.resolvers.go rename to internal/app/graph/resolvers/authorization.resolvers.go index c599032..fe103a4 100644 --- a/graph/resolvers/authorization.resolvers.go +++ b/internal/app/graph/resolvers/authorization.resolvers.go @@ -2,14 +2,14 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" - "github.com/go-graphql/graph/generated" + "github.com/go-graphql/internal/app/graph/generated" + "github.com/go-graphql/internal/app/models" "github.com/go-graphql/logger" - "github.com/go-graphql/models" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/create_pokemon.resolvers.go b/internal/app/graph/resolvers/create_pokemon.resolvers.go similarity index 85% rename from graph/resolvers/create_pokemon.resolvers.go rename to internal/app/graph/resolvers/create_pokemon.resolvers.go index e6adf83..1a3cbd1 100644 --- a/graph/resolvers/create_pokemon.resolvers.go +++ b/internal/app/graph/resolvers/create_pokemon.resolvers.go @@ -2,15 +2,15 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" - "github.com/go-graphql/auth" - "github.com/go-graphql/graph/generated" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/graph/generated" + "github.com/go-graphql/internal/app/models" "github.com/go-graphql/logger" - "github.com/go-graphql/models" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/create_pokemon.resolvers_test.go b/internal/app/graph/resolvers/create_pokemon.resolvers_test.go similarity index 88% rename from graph/resolvers/create_pokemon.resolvers_test.go rename to internal/app/graph/resolvers/create_pokemon.resolvers_test.go index c28d221..3976d94 100644 --- a/graph/resolvers/create_pokemon.resolvers_test.go +++ b/internal/app/graph/resolvers/create_pokemon.resolvers_test.go @@ -4,11 +4,11 @@ import ( "context" "testing" - "github.com/go-graphql/auth" - "github.com/go-graphql/errors" - "github.com/go-graphql/graph/generated" - "github.com/go-graphql/mocks" - "github.com/go-graphql/models" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/errors" + "github.com/go-graphql/internal/app/graph/generated" + "github.com/go-graphql/internal/app/mocks" + "github.com/go-graphql/internal/app/models" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" ) diff --git a/graph/resolvers/delete_pokemon.resolvers.go b/internal/app/graph/resolvers/delete_pokemon.resolvers.go similarity index 87% rename from graph/resolvers/delete_pokemon.resolvers.go rename to internal/app/graph/resolvers/delete_pokemon.resolvers.go index 2a64aaa..626c9fa 100644 --- a/graph/resolvers/delete_pokemon.resolvers.go +++ b/internal/app/graph/resolvers/delete_pokemon.resolvers.go @@ -2,14 +2,14 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" - "github.com/go-graphql/auth" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/models" "github.com/go-graphql/logger" - "github.com/go-graphql/models" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/entity.resolvers.go b/internal/app/graph/resolvers/entity.resolvers.go similarity index 88% rename from graph/resolvers/entity.resolvers.go rename to internal/app/graph/resolvers/entity.resolvers.go index 5a3f53c..022a783 100644 --- a/graph/resolvers/entity.resolvers.go +++ b/internal/app/graph/resolvers/entity.resolvers.go @@ -2,14 +2,14 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" "strconv" - "github.com/go-graphql/graph/generated" - "github.com/go-graphql/models" + "github.com/go-graphql/internal/app/graph/generated" + "github.com/go-graphql/internal/app/models" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/pokemon.resolvers.go b/internal/app/graph/resolvers/pokemon.resolvers.go similarity index 89% rename from graph/resolvers/pokemon.resolvers.go rename to internal/app/graph/resolvers/pokemon.resolvers.go index fa4995f..8e71fb2 100644 --- a/graph/resolvers/pokemon.resolvers.go +++ b/internal/app/graph/resolvers/pokemon.resolvers.go @@ -2,16 +2,16 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" "strconv" - "github.com/go-graphql/auth" - "github.com/go-graphql/graph/generated" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/graph/generated" + "github.com/go-graphql/internal/app/models" "github.com/go-graphql/logger" - "github.com/go-graphql/models" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/pokemons.resolvers.go b/internal/app/graph/resolvers/pokemons.resolvers.go similarity index 83% rename from graph/resolvers/pokemons.resolvers.go rename to internal/app/graph/resolvers/pokemons.resolvers.go index 0a46b88..00c5afd 100644 --- a/graph/resolvers/pokemons.resolvers.go +++ b/internal/app/graph/resolvers/pokemons.resolvers.go @@ -2,15 +2,15 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" - "github.com/go-graphql/auth" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/models" + "github.com/go-graphql/internal/app/utils" "github.com/go-graphql/logger" - "github.com/go-graphql/models" - "github.com/go-graphql/utils" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/resolver.go b/internal/app/graph/resolvers/resolver.go similarity index 94% rename from graph/resolvers/resolver.go rename to internal/app/graph/resolvers/resolver.go index 6210446..02f40d7 100644 --- a/graph/resolvers/resolver.go +++ b/internal/app/graph/resolvers/resolver.go @@ -1,7 +1,7 @@ package resolvers import ( - "github.com/go-graphql/service" + "github.com/go-graphql/internal/app/service" ) // This file will not be regenerated automatically. diff --git a/graph/resolvers/types.resolvers.go b/internal/app/graph/resolvers/types.resolvers.go similarity index 82% rename from graph/resolvers/types.resolvers.go rename to internal/app/graph/resolvers/types.resolvers.go index ea37bcf..24d10dc 100644 --- a/graph/resolvers/types.resolvers.go +++ b/internal/app/graph/resolvers/types.resolvers.go @@ -2,15 +2,15 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" - "github.com/go-graphql/auth" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/models" + "github.com/go-graphql/internal/app/utils" "github.com/go-graphql/logger" - "github.com/go-graphql/models" - "github.com/go-graphql/utils" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/resolvers/update_pokemon.resolvers.go b/internal/app/graph/resolvers/update_pokemon.resolvers.go similarity index 85% rename from graph/resolvers/update_pokemon.resolvers.go rename to internal/app/graph/resolvers/update_pokemon.resolvers.go index eb09d45..d4121aa 100644 --- a/graph/resolvers/update_pokemon.resolvers.go +++ b/internal/app/graph/resolvers/update_pokemon.resolvers.go @@ -2,14 +2,14 @@ package resolvers // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. -// Code generated by github.com/99designs/gqlgen version v0.17.21 DO NOT EDIT. +// Code generated by github.com/99designs/gqlgen version v0.17.34 import ( "context" - "github.com/go-graphql/auth" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/models" "github.com/go-graphql/logger" - "github.com/go-graphql/models" "github.com/sirupsen/logrus" "github.com/vektah/gqlparser/gqlerror" ) diff --git a/graph/schemas/authorization.graphqls b/internal/app/graph/schemas/authorization.graphqls similarity index 100% rename from graph/schemas/authorization.graphqls rename to internal/app/graph/schemas/authorization.graphqls diff --git a/graph/schemas/federation.graphqls b/internal/app/graph/schemas/federation.graphqls similarity index 100% rename from graph/schemas/federation.graphqls rename to internal/app/graph/schemas/federation.graphqls diff --git a/graph/schemas/pokemon/create_pokemon.graphqls b/internal/app/graph/schemas/pokemon/create_pokemon.graphqls similarity index 100% rename from graph/schemas/pokemon/create_pokemon.graphqls rename to internal/app/graph/schemas/pokemon/create_pokemon.graphqls diff --git a/graph/schemas/pokemon/delete_pokemon.graphqls b/internal/app/graph/schemas/pokemon/delete_pokemon.graphqls similarity index 100% rename from graph/schemas/pokemon/delete_pokemon.graphqls rename to internal/app/graph/schemas/pokemon/delete_pokemon.graphqls diff --git a/graph/schemas/pokemon/pokemon.graphqls b/internal/app/graph/schemas/pokemon/pokemon.graphqls similarity index 100% rename from graph/schemas/pokemon/pokemon.graphqls rename to internal/app/graph/schemas/pokemon/pokemon.graphqls diff --git a/graph/schemas/pokemon/pokemons.graphqls b/internal/app/graph/schemas/pokemon/pokemons.graphqls similarity index 100% rename from graph/schemas/pokemon/pokemons.graphqls rename to internal/app/graph/schemas/pokemon/pokemons.graphqls diff --git a/graph/schemas/pokemon/update_pokemon.graphqls b/internal/app/graph/schemas/pokemon/update_pokemon.graphqls similarity index 100% rename from graph/schemas/pokemon/update_pokemon.graphqls rename to internal/app/graph/schemas/pokemon/update_pokemon.graphqls diff --git a/graph/schemas/pokemon_types/pokemon_type.graphqls b/internal/app/graph/schemas/pokemon_types/pokemon_type.graphqls similarity index 100% rename from graph/schemas/pokemon_types/pokemon_type.graphqls rename to internal/app/graph/schemas/pokemon_types/pokemon_type.graphqls diff --git a/graph/schemas/scalars.graphqls b/internal/app/graph/schemas/scalars.graphqls similarity index 100% rename from graph/schemas/scalars.graphqls rename to internal/app/graph/schemas/scalars.graphqls diff --git a/graph/schemas/type/types.graphqls b/internal/app/graph/schemas/type/types.graphqls similarity index 100% rename from graph/schemas/type/types.graphqls rename to internal/app/graph/schemas/type/types.graphqls diff --git a/mocks/mock_PokemonService.go b/internal/app/mocks/mock_PokemonService.go similarity index 98% rename from mocks/mock_PokemonService.go rename to internal/app/mocks/mock_PokemonService.go index a3ace20..b6bb182 100644 --- a/mocks/mock_PokemonService.go +++ b/internal/app/mocks/mock_PokemonService.go @@ -8,7 +8,7 @@ import ( context "context" reflect "reflect" - models "github.com/go-graphql/models" + models "github.com/go-graphql/internal/app/models" gomock "github.com/golang/mock/gomock" ) diff --git a/mocks/mock_TypeService.go b/internal/app/mocks/mock_TypeService.go similarity index 97% rename from mocks/mock_TypeService.go rename to internal/app/mocks/mock_TypeService.go index 22db395..8a32104 100644 --- a/mocks/mock_TypeService.go +++ b/internal/app/mocks/mock_TypeService.go @@ -8,7 +8,7 @@ import ( context "context" reflect "reflect" - models "github.com/go-graphql/models" + models "github.com/go-graphql/internal/app/models" gomock "github.com/golang/mock/gomock" ) diff --git a/models/models_gen.go b/internal/app/models/models_gen.go similarity index 78% rename from models/models_gen.go rename to internal/app/models/models_gen.go index fb6f343..b37dd0b 100644 --- a/models/models_gen.go +++ b/internal/app/models/models_gen.go @@ -40,18 +40,12 @@ type PokemonType struct { Slot int `json:"slot"` } -type Type struct { - ID string `json:"id"` - Name string `json:"name"` - DamageTypeID int `json:"damageTypeID"` -} - type UpdatePokemonInput struct { ID int `json:"id"` - Name *string `json:"name"` - Height *int `json:"height"` - Weight *int `json:"weight"` - BaseExperience *int `json:"baseExperience"` + Name *string `json:"name,omitempty"` + Height *int `json:"height,omitempty"` + Weight *int `json:"weight,omitempty"` + BaseExperience *int `json:"baseExperience,omitempty"` } type UpdatePokemonPayload struct { diff --git a/models/pokemon.go b/internal/app/models/pokemon.go similarity index 69% rename from models/pokemon.go rename to internal/app/models/pokemon.go index beacf1f..bdc0ad0 100644 --- a/models/pokemon.go +++ b/internal/app/models/pokemon.go @@ -11,3 +11,10 @@ type Pokemon struct { } func (Pokemon) IsEntity() {} + +// Type - +type Type struct { + ID string `json:"id"` + Name string `json:"name"` + DamageTypeID int `json:"damageTypeID"` +} diff --git a/repository/pokemon.repository.go b/internal/app/repository/pokemon.repository.go similarity index 98% rename from repository/pokemon.repository.go rename to internal/app/repository/pokemon.repository.go index bf45310..cf4a753 100644 --- a/repository/pokemon.repository.go +++ b/internal/app/repository/pokemon.repository.go @@ -6,7 +6,7 @@ import ( "strconv" "github.com/go-graphql/config" - "github.com/go-graphql/models" + "github.com/go-graphql/internal/app/models" ) // PokemonRepositoryInterface - . diff --git a/repository/type.repository.go b/internal/app/repository/type.repository.go similarity index 97% rename from repository/type.repository.go rename to internal/app/repository/type.repository.go index 983c911..b5ec7a4 100644 --- a/repository/type.repository.go +++ b/internal/app/repository/type.repository.go @@ -2,7 +2,7 @@ package repository import ( "github.com/go-graphql/config" - "github.com/go-graphql/models" + "github.com/go-graphql/internal/app/models" ) // TypeRepositoryInterface - . diff --git a/service/auth.service.go b/internal/app/service/auth.service.go similarity index 92% rename from service/auth.service.go rename to internal/app/service/auth.service.go index 81286f6..a21b499 100644 --- a/service/auth.service.go +++ b/internal/app/service/auth.service.go @@ -7,9 +7,9 @@ import ( "time" - "github.com/go-graphql/auth" - "github.com/go-graphql/errors" - "github.com/go-graphql/models" + "github.com/go-graphql/internal/app/auth" + "github.com/go-graphql/internal/app/errors" + "github.com/go-graphql/internal/app/models" "github.com/golang-jwt/jwt" ) diff --git a/service/pokemon.service.go b/internal/app/service/pokemon.service.go similarity index 94% rename from service/pokemon.service.go rename to internal/app/service/pokemon.service.go index 5b2641e..795c366 100644 --- a/service/pokemon.service.go +++ b/internal/app/service/pokemon.service.go @@ -3,8 +3,8 @@ package service import ( "context" - "github.com/go-graphql/models" - "github.com/go-graphql/repository" + "github.com/go-graphql/internal/app/models" + "github.com/go-graphql/internal/app/repository" ) // PokemonServiceInterface - . diff --git a/service/type.service.go b/internal/app/service/type.service.go similarity index 90% rename from service/type.service.go rename to internal/app/service/type.service.go index 6eb91fd..233b10a 100644 --- a/service/type.service.go +++ b/internal/app/service/type.service.go @@ -3,8 +3,8 @@ package service import ( "context" - "github.com/go-graphql/models" - "github.com/go-graphql/repository" + "github.com/go-graphql/internal/app/models" + "github.com/go-graphql/internal/app/repository" ) // TypeServiceInterface - . diff --git a/utils/utils.go b/internal/app/utils/utils.go similarity index 100% rename from utils/utils.go rename to internal/app/utils/utils.go diff --git a/utils/utils_test.go b/internal/app/utils/utils_test.go similarity index 100% rename from utils/utils_test.go rename to internal/app/utils/utils_test.go diff --git a/logger/logger.go b/logger/logger.go index bf9ea82..72d2f41 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -1,17 +1,22 @@ package logger import ( - log "github.com/sirupsen/logrus" + nested "github.com/antonfisher/nested-logrus-formatter" + logrus "github.com/sirupsen/logrus" ) // Log - logrus logging. // //revive:disable:import-shadowing -var ( - Log *log.Logger -) +var Log *logrus.Logger // SetupLog - return logrus. func init() { - Log = log.New() + log := logrus.New() + log.SetFormatter(&nested.Formatter{ + HideKeys: true, + FieldsOrder: []string{"component", "category"}, + }) + + Log = log }