From 9adc7b81ac27c157e597d369e4499353f0f6b0b0 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Mon, 17 Jul 2023 15:21:34 -0400 Subject: [PATCH 01/54] Update gqlparser to v2.5.8 (#2716) Signed-off-by: Steve Coffman --- _examples/go.mod | 2 +- _examples/go.sum | 4 ++-- _examples/websocket-initfunc/server/go.mod | 2 +- _examples/websocket-initfunc/server/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/_examples/go.mod b/_examples/go.mod index 1da124d769..d26124f0ab 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -12,7 +12,7 @@ require ( github.com/rs/cors v1.9.0 github.com/stretchr/testify v1.8.2 github.com/vektah/dataloaden v0.3.0 - github.com/vektah/gqlparser/v2 v2.5.7 + github.com/vektah/gqlparser/v2 v2.5.8 sourcegraph.com/sourcegraph/appdash v0.0.0-20211028080628-e2786a622600 ) diff --git a/_examples/go.sum b/_examples/go.sum index 5272749751..8e76230a20 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -66,8 +66,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/vektah/dataloaden v0.3.0 h1:ZfVN2QD6swgvp+tDqdH/OIT/wu3Dhu0cus0k5gIZS84= github.com/vektah/dataloaden v0.3.0/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= -github.com/vektah/gqlparser/v2 v2.5.7 h1:QnW4lWFSaycZ1jqvVaQ/tDXGGzQfqAuWdyC4S9g/KVM= -github.com/vektah/gqlparser/v2 v2.5.7/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= +github.com/vektah/gqlparser/v2 v2.5.8 h1:pm6WOnGdzFOCfcQo9L3+xzW51mKrlwTEg4Wr7AH1JW4= +github.com/vektah/gqlparser/v2 v2.5.8/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/_examples/websocket-initfunc/server/go.mod b/_examples/websocket-initfunc/server/go.mod index 494e3cbf33..6d71b73d17 100644 --- a/_examples/websocket-initfunc/server/go.mod +++ b/_examples/websocket-initfunc/server/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-chi/chi v1.5.4 github.com/gorilla/websocket v1.5.0 github.com/rs/cors v1.9.0 - github.com/vektah/gqlparser/v2 v2.5.7 + github.com/vektah/gqlparser/v2 v2.5.8 ) require ( diff --git a/_examples/websocket-initfunc/server/go.sum b/_examples/websocket-initfunc/server/go.sum index 6be6085a3d..10fb21231c 100644 --- a/_examples/websocket-initfunc/server/go.sum +++ b/_examples/websocket-initfunc/server/go.sum @@ -31,8 +31,8 @@ github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NF github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/vektah/gqlparser/v2 v2.5.7 h1:QnW4lWFSaycZ1jqvVaQ/tDXGGzQfqAuWdyC4S9g/KVM= -github.com/vektah/gqlparser/v2 v2.5.7/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= +github.com/vektah/gqlparser/v2 v2.5.8 h1:pm6WOnGdzFOCfcQo9L3+xzW51mKrlwTEg4Wr7AH1JW4= +github.com/vektah/gqlparser/v2 v2.5.8/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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= diff --git a/go.mod b/go.mod index 62fd40b813..141c03e3a3 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.25.5 - github.com/vektah/gqlparser/v2 v2.5.7 + github.com/vektah/gqlparser/v2 v2.5.8 golang.org/x/text v0.9.0 golang.org/x/tools v0.9.3 google.golang.org/protobuf v1.30.0 diff --git a/go.sum b/go.sum index 309f798936..32203df77f 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ 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/v2 v2.5.7 h1:QnW4lWFSaycZ1jqvVaQ/tDXGGzQfqAuWdyC4S9g/KVM= -github.com/vektah/gqlparser/v2 v2.5.7/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= +github.com/vektah/gqlparser/v2 v2.5.8 h1:pm6WOnGdzFOCfcQo9L3+xzW51mKrlwTEg4Wr7AH1JW4= +github.com/vektah/gqlparser/v2 v2.5.8/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.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= From cccc7389c10cdd4ef4eb7b9541dedb0f9cf74a97 Mon Sep 17 00:00:00 2001 From: Rumen Nikiforov Date: Wed, 19 Jul 2023 17:29:25 +0300 Subject: [PATCH 02/54] Added go mod tidy to quick start guide (#2718) Added `go mod tidy` in quick start guide to address issues like #2717, #2651, #2641, #2614 and #2576 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e35db1c123..b11ab55392 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ Still not convinced enough to use **gqlgen**? Compare **gqlgen** with other Go g go run github.com/99designs/gqlgen init + go mod tidy + 4. Start the graphql server go run server.go From b233a01bf7eeb9f9ddc590a7dd72058da28d88df Mon Sep 17 00:00:00 2001 From: Zen Yui Date: Wed, 19 Jul 2023 18:07:47 -0400 Subject: [PATCH 03/54] docs: update dataloader docs (#2719) * docs: update example * docs: update example * fix: import --- docs/content/reference/dataloaders.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/content/reference/dataloaders.md b/docs/content/reference/dataloaders.md index 15cfda3e3e..7e198d5bd6 100644 --- a/docs/content/reference/dataloaders.md +++ b/docs/content/reference/dataloaders.md @@ -64,7 +64,7 @@ go get -u github.com/graph-gophers/dataloader Next, we implement a data loader and a middleware for injecting the data loader on a request context. ```go -package storage +package loaders // import graph gophers with your other imports import ( @@ -137,7 +137,9 @@ func NewLoaders(conn *sql.DB) *Loaders { } // Middleware injects data loaders into the context -func Middleware(loaders *Loaders, next http.Handler) http.Handler { +func Middleware(conn *sql.DB, next http.Handler) http.Handler { + // create a request-scoped data loader + loader := NewLoaders(conn) // return a middleware that injects the loader to the request context return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { nextCtx := context.WithValue(r.Context(), loadersKey, loaders) @@ -164,10 +166,21 @@ func GetUser(ctx context.Context, userID string) (*model.User, error) { ``` +Add the dataloader middleware to your server... +```go +// create the query handler +var srv http.Handler = handler.NewDefaultServer(generated.NewExecutableSchema(...)) +// wrap the query handler with middleware to inject dataloader in requests. +// pass in your dataloader depenendicies, in this case the db connection. +srv = loaders.Middleware(db, srv) +// register the wrapped handler +http.Handle("/query", srv) +``` + Now lets update our resolver to call the dataloader: ```go func (r *todoResolver) User(ctx context.Context, obj *model.Todo) (*model.User, error) { - return storage.GetUser(ctx, obj.UserID) + return loaders.GetUser(ctx, obj.UserID) } ``` From 16c9eb64ed04218e927a74199a57f951bfb452b1 Mon Sep 17 00:00:00 2001 From: Zen Yui Date: Thu, 20 Jul 2023 07:15:06 -0400 Subject: [PATCH 04/54] Fix docs (#2722) * docs: fix variable names in dataloader sample * fix: request-scoped middleware --- docs/content/reference/dataloaders.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/content/reference/dataloaders.md b/docs/content/reference/dataloaders.md index 7e198d5bd6..a986fe1b30 100644 --- a/docs/content/reference/dataloaders.md +++ b/docs/content/reference/dataloaders.md @@ -138,11 +138,12 @@ func NewLoaders(conn *sql.DB) *Loaders { // Middleware injects data loaders into the context func Middleware(conn *sql.DB, next http.Handler) http.Handler { - // create a request-scoped data loader - loader := NewLoaders(conn) // return a middleware that injects the loader to the request context return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - nextCtx := context.WithValue(r.Context(), loadersKey, loaders) + // create a request-scoped data loader + loader := NewLoaders(conn) + // inject to context + nextCtx := context.WithValue(r.Context(), loadersKey, loader) r = r.WithContext(nextCtx) next.ServeHTTP(w, r) }) @@ -155,8 +156,8 @@ func For(ctx context.Context) *Loaders { // GetUser wraps the User dataloader for efficient retrieval by user ID func GetUser(ctx context.Context, userID string) (*model.User, error) { - loaders := For(ctx) - thunk := loaders.UserLoader.Load(ctx, dataloader.StringKey(userID)) + loader := For(ctx) + thunk := loader.UserLoader.Load(ctx, dataloader.StringKey(userID)) result, err := thunk() if err != nil { return nil, err From bda3026043f187bf00f039d1c3648d5b1a8e4998 Mon Sep 17 00:00:00 2001 From: Rumen Nikiforov Date: Thu, 20 Jul 2023 22:38:21 +0300 Subject: [PATCH 05/54] Fixed Data Loader docs (#2723) Also updated to v7 --- docs/content/reference/dataloaders.md | 143 ++++++++++++++------------ 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/docs/content/reference/dataloaders.md b/docs/content/reference/dataloaders.md index a986fe1b30..479b516773 100644 --- a/docs/content/reference/dataloaders.md +++ b/docs/content/reference/dataloaders.md @@ -18,22 +18,30 @@ query { todos { user { name } } } and the `todo.user` resolver reads the `User` from a database... ```go func (r *todoResolver) User(ctx context.Context, obj *model.Todo) (*model.User, error) { - res := db.LogAndQuery( - r.Conn, - "SELECT id, name FROM users WHERE id = ?", - obj.UserID, - ) - defer res.Close() - - if !res.Next() { - return nil, nil + stmt, err := r.db.PrepareContext(ctx, "SELECT id, name FROM users WHERE id = ?") + if err != nil { + return nil, err } + defer stmt.Close() + + rows, err := stmt.QueryContext(ctx, obj.UserID) + if err != nil { + return nil, err + } + defer rows.Close() + + if !rows.Next() { + return nil, rows.Err() + } + var user model.User - if err := res.Scan(&user.ID, &user.Name); err != nil { - panic(err) + if err := rows.Scan(&user.ID, &user.Name); err != nil { + return nil, err } return &user, nil } + + ``` The query executor will call the `Query.Todos` resolver which does a `select * from todo` and returns `N` todos. If the nested `User` is selected, the above `UserRaw` resolver will run a separate query for each user, resulting in `N+1` database queries. @@ -58,7 +66,7 @@ Dataloaders allow us to consolidate the fetching of `todo.user` across all resol We're going to use [graph-gophers/dataloader](https://github.com/graph-gophers/dataloader) to implement a dataloader for bulk-fetching users. ```bash -go get -u github.com/graph-gophers/dataloader +go get -u github.com/graph-gophers/dataloader/v7 ``` Next, we implement a data loader and a middleware for injecting the data loader on a request context. @@ -68,7 +76,13 @@ package loaders // import graph gophers with your other imports import ( - "github.com/graph-gophers/dataloader" + "context" + "database/sql" + "net/http" + "strings" + "time" + + "github.com/graph-gophers/dataloader/v7" ) type ctxKey string @@ -77,74 +91,66 @@ const ( loadersKey = ctxKey("dataloaders") ) -// UserReader reads Users from a database -type UserReader struct { - conn *sql.DB +// userReader reads Users from a database +type userReader struct { + db *sql.DB } -// GetUsers implements a batch function that can retrieve many users by ID, +// getUsers implements a batch function that can retrieve many users by ID, // for use in a dataloader -func (u *UserReader) GetUsers(ctx context.Context, keys dataloader.Keys) []*dataloader.Result { - // read all requested users in a single query - userIDs := make([]string, len(keys)) - for ix, key := range keys { - userIDs[ix] = key.String() +func (u *userReader) getUsers(ctx context.Context, userIds []string) []*dataloader.Result[*model.User] { + stmt, err := u.db.PrepareContext(ctx, `SELECT id, name FROM users WHERE id IN (?`+strings.Repeat(",?", len(userIds)-1)+`)`) + if err != nil { + return handleError[*model.User](len(userIds), err) } - res := u.db.Exec( - r.Conn, - "SELECT id, name - FROM users - WHERE id IN (?" + strings.Repeat(",?", len(userIDs-1)) + ")", - userIDs..., - ) - defer res.Close() - // return User records into a map by ID - userById := map[string]*model.User{} - for res.Next() { - user := model.User{} - if err := res.Scan(&user.ID, &user.Name); err != nil { - panic(err) - } - userById[user.ID] = &user + defer stmt.Close() + + rows, err := stmt.QueryContext(ctx, userIds) + if err != nil { + return handleError[*model.User](len(userIds), err) } - // return users in the same order requested - output := make([]*dataloader.Result, len(keys)) - for index, userKey := range keys { - user, ok := userById[userKey.String()] - if ok { - output[index] = &dataloader.Result{Data: user, Error: nil} - } else { - err := fmt.Errorf("user not found %s", userKey.String()) - output[index] = &dataloader.Result{Data: nil, Error: err} + defer rows.Close() + + result := make([]*dataloader.Result[*model.User], 0, len(userIds)) + for rows.Next() { + var user model.User + if err := rows.Scan(&user.ID, &user.Name); err != nil { + result = append(result, &dataloader.Result[*model.User]{Error: err}) + continue } + result = append(result, &dataloader.Result[*model.User]{Data: &user}) + } + return result +} + +// handleError creates array of result with the same error repeated for as many items requested +func handleError[T any](itemsLength int, err error) []*dataloader.Result[T] { + result := make([]*dataloader.Result[T], itemsLength) + for i := 0; i < itemsLength; i++ { + result[i] = &dataloader.Result[T]{Error: err} } - return output + return result } // Loaders wrap your data loaders to inject via middleware type Loaders struct { - UserLoader *dataloader.Loader + UserLoader *dataloader.Loader[string, *model.User] } // NewLoaders instantiates data loaders for the middleware func NewLoaders(conn *sql.DB) *Loaders { // define the data loader - userReader := &UserReader{conn: conn} - loaders := &Loaders{ - UserLoader: dataloader.NewBatchedLoader(userReader.GetUsers), + ur := &userReader{db: conn} + return &Loaders{ + UserLoader: dataloader.NewBatchedLoader(ur.getUsers, dataloader.WithWait[string, *model.User](time.Millisecond)), } - return loaders } // Middleware injects data loaders into the context -func Middleware(conn *sql.DB, next http.Handler) http.Handler { +func Middleware(loaders *Loaders, next http.Handler) http.Handler { // return a middleware that injects the loader to the request context return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // create a request-scoped data loader - loader := NewLoaders(conn) - // inject to context - nextCtx := context.WithValue(r.Context(), loadersKey, loader) - r = r.WithContext(nextCtx) + r = r.WithContext(context.WithValue(r.Context(), loadersKey, loaders)) next.ServeHTTP(w, r) }) } @@ -154,15 +160,16 @@ func For(ctx context.Context) *Loaders { return ctx.Value(loadersKey).(*Loaders) } -// GetUser wraps the User dataloader for efficient retrieval by user ID +// GetUser returns single user by id efficiently func GetUser(ctx context.Context, userID string) (*model.User, error) { - loader := For(ctx) - thunk := loader.UserLoader.Load(ctx, dataloader.StringKey(userID)) - result, err := thunk() - if err != nil { - return nil, err - } - return result.(*model.User), nil + loaders := For(ctx) + return loaders.UserLoader.Load(ctx, userID)() +} + +// GetUsers returns many users by ids efficiently +func GetUsers(ctx context.Context, userIDs []string) ([]*model.User, []error) { + loaders := For(ctx) + return loaders.UserLoader.LoadMany(ctx, userIDs)() } ``` @@ -172,7 +179,7 @@ Add the dataloader middleware to your server... // create the query handler var srv http.Handler = handler.NewDefaultServer(generated.NewExecutableSchema(...)) // wrap the query handler with middleware to inject dataloader in requests. -// pass in your dataloader depenendicies, in this case the db connection. +// pass in your dataloader dependencies, in this case the db connection. srv = loaders.Middleware(db, srv) // register the wrapped handler http.Handle("/query", srv) From febf9566224b3e3ad0e32903fd46d9005d6a7748 Mon Sep 17 00:00:00 2001 From: penard-cb <135390596+penard-cb@users.noreply.github.com> Date: Fri, 21 Jul 2023 21:46:32 -0400 Subject: [PATCH 06/54] Make the resolver implementation configurable via a new template resolver.gotpl (#2720) * Make an optional resolver.gotpl ResolverTemplate to implement a custom resolver * Add test * Add documetation for the new resolver option * Change the tab to spaces * remove unecessary test assertion :/ --- codegen/config/resolver.go | 1 + docs/content/config.md | 2 + plugin/resolvergen/resolver.go | 16 ++++++ plugin/resolvergen/resolver_test.go | 16 ++++++ .../customResolverTemplate.gotpl | 54 +++++++++++++++++++ .../testdata/resolvertemplate/gqlgen.yml | 17 ++++++ .../testdata/resolvertemplate/out/resolver.go | 7 +++ .../resolvertemplate/out/schema.resolvers.go | 35 ++++++++++++ 8 files changed, 148 insertions(+) create mode 100644 plugin/resolvergen/testdata/resolvertemplate/customResolverTemplate.gotpl create mode 100644 plugin/resolvergen/testdata/resolvertemplate/gqlgen.yml create mode 100644 plugin/resolvergen/testdata/resolvertemplate/out/resolver.go create mode 100644 plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go diff --git a/codegen/config/resolver.go b/codegen/config/resolver.go index a3ec38f8e2..cb5fb72b36 100644 --- a/codegen/config/resolver.go +++ b/codegen/config/resolver.go @@ -17,6 +17,7 @@ type ResolverConfig struct { Layout ResolverLayout `yaml:"layout,omitempty"` DirName string `yaml:"dir"` OmitTemplateComment bool `yaml:"omit_template_comment,omitempty"` + ResolverTemplate string `yaml:"resolver_template,omitempty"` } type ResolverLayout string diff --git a/docs/content/config.md b/docs/content/config.md index 7233055346..86c91a47c3 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -39,6 +39,8 @@ resolver: filename_template: "{name}.resolvers.go" # Optional: turn on to not generate template comments above resolvers # omit_template_comment: false + # Optional: Pass in a path to a new gotpl template to use for generating resolvers + # resolver_template: [your/path/resolver.gotpl] # Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models # struct_tag: json diff --git a/plugin/resolvergen/resolver.go b/plugin/resolvergen/resolver.go index 09cfbab63b..215bc469df 100644 --- a/plugin/resolvergen/resolver.go +++ b/plugin/resolvergen/resolver.go @@ -81,6 +81,10 @@ func (m *Plugin) generateSingleFile(data *codegen.Data) error { OmitTemplateComment: data.Config.Resolver.OmitTemplateComment, } + if data.Config.Resolver.ResolverTemplate != "" { + resolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) + } + return templates.Render(templates.Options{ PackageName: data.Config.Resolver.Package, FileNotice: `// THIS CODE IS A STARTING POINT ONLY. IT WILL NOT BE UPDATED WITH SCHEMA CHANGES.`, @@ -159,6 +163,10 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { file.RemainingSource = rewriter.RemainingSource(filename) } + if data.Config.Resolver.ResolverTemplate != "" { + resolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) + } + for filename, file := range files { resolverBuild := &ResolverBuild{ File: file, @@ -257,3 +265,11 @@ func gqlToResolverName(base string, gqlname, filenameTmpl string) string { filename := strings.ReplaceAll(filenameTmpl, "{name}", strings.TrimSuffix(gqlname, ext)) return filepath.Join(base, filename) } + +func readResolverTemplate(customResolverTemplate string) string { + contentBytes, err := os.ReadFile(customResolverTemplate) + if err != nil { + panic(err) + } + return string(contentBytes) +} diff --git a/plugin/resolvergen/resolver_test.go b/plugin/resolvergen/resolver_test.go index 5a1300113c..2cf9713f7c 100644 --- a/plugin/resolvergen/resolver_test.go +++ b/plugin/resolvergen/resolver_test.go @@ -83,6 +83,22 @@ func TestOmitTemplateComment(t *testing.T) { assertNoErrors(t, "github.com/99designs/gqlgen/plugin/resolvergen/testdata/omit_template_comment/out") } +func TestCustomResolverTemplate(t *testing.T) { + _ = syscall.Unlink("testdata/resolvertemplate/out/resolver.go") + cfg, err := config.LoadConfig("testdata/resolvertemplate/gqlgen.yml") + require.NoError(t, err) + p := Plugin{} + + require.NoError(t, cfg.Init()) + + data, err := codegen.BuildData(cfg) + if err != nil { + panic(err) + } + + require.NoError(t, p.GenerateCode(data)) +} + func testFollowSchemaPersistence(t *testing.T, dir string) { _ = syscall.Unlink(dir + "/out/resolver.go") diff --git a/plugin/resolvergen/testdata/resolvertemplate/customResolverTemplate.gotpl b/plugin/resolvergen/testdata/resolvertemplate/customResolverTemplate.gotpl new file mode 100644 index 0000000000..ff652f0148 --- /dev/null +++ b/plugin/resolvergen/testdata/resolvertemplate/customResolverTemplate.gotpl @@ -0,0 +1,54 @@ +{{ reserveImport "context" }} +{{ reserveImport "fmt" }} +{{ reserveImport "io" }} +{{ reserveImport "strconv" }} +{{ reserveImport "time" }} +{{ reserveImport "sync" }} +{{ reserveImport "errors" }} +{{ reserveImport "bytes" }} +{{ reserveImport "encoding/json" }} + +{{ reserveImport "github.com/vektah/gqlparser/v2" }} +{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }} + +{{ .Imports }} + +{{ if .HasRoot }} + type {{.ResolverType}} struct {} +{{ end }} + +{{ range $resolver := .Resolvers -}} + {{ if $resolver.Comment -}} + // {{ $resolver.Comment }} + {{- else if not $.OmitTemplateComment -}} + // {{ $resolver.Field.GoFieldName }} is the resolver for the {{ $resolver.Field.Name }} field. + {{- end }} + func (r *{{lcFirst $resolver.Object.Name}}{{ucFirst $.ResolverType}}) {{$resolver.Field.GoFieldName}}{{ with $resolver.PrevDecl }}{{ $resolver.Field.ShortResolverSignature .Type }}{{ else }}{{ $resolver.Field.ShortResolverDeclaration }}{{ end }}{ + // Custom Resolver implementation + panic(fmt.Errorf("custom Resolver not implemented: {{ $resolver.Field.GoFieldName }} - {{lcFirst $resolver.Field.GoFieldName }}")) + } + +{{ end }} + +{{ range $object := .Objects -}} + {{ if not $.OmitTemplateComment -}} + // {{ucFirst $object.Name}} returns {{ $object.ResolverInterface | ref }} implementation. + {{- end }} + func (r *{{$.ResolverType}}) {{ucFirst $object.Name}}() {{ $object.ResolverInterface | ref }} { return &{{lcFirst $object.Name}}{{ucFirst $.ResolverType}}{r} } +{{ end }} + +{{ range $object := .Objects -}} + type {{lcFirst $object.Name}}{{ucFirst $.ResolverType}} struct { *{{$.ResolverType}} } +{{ end }} + +{{ if (ne .RemainingSource "") }} + // !!! WARNING !!! + // The code below was going to be deleted when updating resolvers. It has been copied here so you have + // one last chance to move it out of harms way if you want. There are two reasons this happens: + // - When renaming or deleting a resolver the old code will be put in here. You can safely delete + // it when you're done. + // - You have helper methods in this file. Move them out to keep these resolver files clean. + {{ .RemainingSource }} +{{ end }} diff --git a/plugin/resolvergen/testdata/resolvertemplate/gqlgen.yml b/plugin/resolvergen/testdata/resolvertemplate/gqlgen.yml new file mode 100644 index 0000000000..c7ce0aaddd --- /dev/null +++ b/plugin/resolvergen/testdata/resolvertemplate/gqlgen.yml @@ -0,0 +1,17 @@ +schema: + - "testdata/schema.graphql" + +exec: + filename: testdata/singlefile/out/ignored.go +model: + filename: testdata/singlefile/out/generated.go +resolver: + type: CustomResolverType + layout: follow-schema + dir: testdata/resolvertemplate/out + filename_template: "{name}.resolvers.go" + resolver_template: "testdata/resolvertemplate/customResolverTemplate.gotpl" + +models: + Resolver: + model: github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out.Resolver diff --git a/plugin/resolvergen/testdata/resolvertemplate/out/resolver.go b/plugin/resolvergen/testdata/resolvertemplate/out/resolver.go new file mode 100644 index 0000000000..640b3c53ff --- /dev/null +++ b/plugin/resolvergen/testdata/resolvertemplate/out/resolver.go @@ -0,0 +1,7 @@ +package out + +// This file will not be regenerated automatically. +// +// It serves as dependency injection for your app, add any dependencies you require here. + +type CustomResolverType struct{} diff --git a/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go b/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go new file mode 100644 index 0000000000..17018884cb --- /dev/null +++ b/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go @@ -0,0 +1,35 @@ +package out + +// 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.35-dev + +import ( + "context" + "fmt" + + customresolver "github.com/99designs/gqlgen/plugin/resolvergen/testdata/singlefile/out" +) + +// Resolver is the resolver for the resolver field. +func (r *queryCustomResolverType) Resolver(ctx context.Context) (*customresolver.Resolver, error) { + // Custom Resolver implementation + panic(fmt.Errorf("custom Resolver not implemented: Resolver - resolver")) +} + +// Name is the resolver for the name field. +func (r *resolverCustomResolverType) Name(ctx context.Context, obj *customresolver.Resolver) (string, error) { + // Custom Resolver implementation + panic(fmt.Errorf("custom Resolver not implemented: Name - name")) +} + +// Query returns customresolver.QueryResolver implementation. +func (r *CustomResolverType) Query() customresolver.QueryResolver { return &queryCustomResolverType{r} } + +// Resolver returns customresolver.ResolverResolver implementation. +func (r *CustomResolverType) Resolver() customresolver.ResolverResolver { + return &resolverCustomResolverType{r} +} + +type queryCustomResolverType struct{ *CustomResolverType } +type resolverCustomResolverType struct{ *CustomResolverType } From abe3ffde59d6a0d942a9ac2d1b657287f75efa67 Mon Sep 17 00:00:00 2001 From: penard-cb <135390596+penard-cb@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:47:32 -0400 Subject: [PATCH 07/54] Don't set the package variable for the new Resolver Template (#2725) --- plugin/resolvergen/resolver.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/resolvergen/resolver.go b/plugin/resolvergen/resolver.go index 215bc469df..d5515da35a 100644 --- a/plugin/resolvergen/resolver.go +++ b/plugin/resolvergen/resolver.go @@ -81,8 +81,9 @@ func (m *Plugin) generateSingleFile(data *codegen.Data) error { OmitTemplateComment: data.Config.Resolver.OmitTemplateComment, } + newResolverTemplate := resolverTemplate if data.Config.Resolver.ResolverTemplate != "" { - resolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) + newResolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) } return templates.Render(templates.Options{ @@ -91,7 +92,7 @@ func (m *Plugin) generateSingleFile(data *codegen.Data) error { Filename: data.Config.Resolver.Filename, Data: resolverBuild, Packages: data.Config.Packages, - Template: resolverTemplate, + Template: newResolverTemplate, }) } @@ -162,9 +163,9 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { file.imports = rewriter.ExistingImports(filename) file.RemainingSource = rewriter.RemainingSource(filename) } - + newResolverTemplate := resolverTemplate if data.Config.Resolver.ResolverTemplate != "" { - resolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) + newResolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) } for filename, file := range files { @@ -194,7 +195,7 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { Filename: filename, Data: resolverBuild, Packages: data.Config.Packages, - Template: resolverTemplate, + Template: newResolverTemplate, }) if err != nil { return err From 76d444c15fc1d98538648a229f41ed7b4573bad7 Mon Sep 17 00:00:00 2001 From: penard-cb <135390596+penard-cb@users.noreply.github.com> Date: Tue, 25 Jul 2023 19:25:12 -0400 Subject: [PATCH 08/54] Make models configurable via template (#2730) --- codegen/config/package.go | 7 +- docs/content/config.md | 2 + plugin/modelgen/models.go | 15 ++- plugin/modelgen/models_test.go | 11 ++ plugin/modelgen/out/generated.go | 2 + .../testdata/customModelTemplate.gotpl | 106 ++++++++++++++++++ .../testdata/gqlgen_custom_model_template.yml | 38 +++++++ 7 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 plugin/modelgen/testdata/customModelTemplate.gotpl create mode 100644 plugin/modelgen/testdata/gqlgen_custom_model_template.yml diff --git a/codegen/config/package.go b/codegen/config/package.go index faacd1496f..37692ece7e 100644 --- a/codegen/config/package.go +++ b/codegen/config/package.go @@ -10,9 +10,10 @@ import ( ) type PackageConfig struct { - Filename string `yaml:"filename,omitempty"` - Package string `yaml:"package,omitempty"` - Version int `yaml:"version,omitempty"` + Filename string `yaml:"filename,omitempty"` + Package string `yaml:"package,omitempty"` + Version int `yaml:"version,omitempty"` + ModelTemplate string `yaml:"model_template,omitempty"` } func (c *PackageConfig) ImportPath() string { diff --git a/docs/content/config.md b/docs/content/config.md index 86c91a47c3..1d167e2ef0 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -30,6 +30,8 @@ federation: model: filename: graph/model/models_gen.go package: model + # Optional: Pass in a path to a new gotpl template to use for generating the models + # model_template: [your/path/model.gotpl] # Where should the resolver implementations go? resolver: diff --git a/plugin/modelgen/models.go b/plugin/modelgen/models.go index 6b4f483752..23c2e334d9 100644 --- a/plugin/modelgen/models.go +++ b/plugin/modelgen/models.go @@ -4,6 +4,7 @@ import ( _ "embed" "fmt" "go/types" + "os" "sort" "strings" "text/template" @@ -282,6 +283,10 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { "getInterfaceByName": getInterfaceByName, "generateGetter": generateGetter, } + newModelTemplate := modelTemplate + if cfg.Model.ModelTemplate != "" { + newModelTemplate = readModelTemplate(cfg.Model.ModelTemplate) + } err := templates.Render(templates.Options{ PackageName: cfg.Model.Package, @@ -289,7 +294,7 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { Data: b, GeneratedHeader: true, Packages: cfg.Packages, - Template: modelTemplate, + Template: newModelTemplate, Funcs: funcMap, }) if err != nil { @@ -645,3 +650,11 @@ func findAndHandleCyclicalRelationships(b *ModelBuild) { } } } + +func readModelTemplate(customModelTemplate string) string { + contentBytes, err := os.ReadFile(customModelTemplate) + if err != nil { + panic(err) + } + return string(contentBytes) +} diff --git a/plugin/modelgen/models_test.go b/plugin/modelgen/models_test.go index f4cd43beae..fa15fa010c 100644 --- a/plugin/modelgen/models_test.go +++ b/plugin/modelgen/models_test.go @@ -637,3 +637,14 @@ func Test_splitTagsBySpace(t *testing.T) { }) } } + +func TestCustomTemplate(t *testing.T) { + cfg, err := config.LoadConfig("testdata/gqlgen_custom_model_template.yml") + require.NoError(t, err) + require.NoError(t, cfg.Init()) + p := Plugin{ + MutateHook: mutateHook, + FieldHook: DefaultFieldMutateHook, + } + require.NoError(t, p.MutateConfig(cfg)) +} diff --git a/plugin/modelgen/out/generated.go b/plugin/modelgen/out/generated.go index f90f8b974a..656913e510 100644 --- a/plugin/modelgen/out/generated.go +++ b/plugin/modelgen/out/generated.go @@ -11,6 +11,8 @@ import ( "github.com/99designs/gqlgen/plugin/modelgen/internal/extrafields" ) +// Add any new functions or any additional code/template functionality here + type A interface { IsA() GetA() string diff --git a/plugin/modelgen/testdata/customModelTemplate.gotpl b/plugin/modelgen/testdata/customModelTemplate.gotpl new file mode 100644 index 0000000000..4ff192a297 --- /dev/null +++ b/plugin/modelgen/testdata/customModelTemplate.gotpl @@ -0,0 +1,106 @@ +{{ reserveImport "context" }} +{{ reserveImport "fmt" }} +{{ reserveImport "io" }} +{{ reserveImport "strconv" }} +{{ reserveImport "time" }} +{{ reserveImport "sync" }} +{{ reserveImport "errors" }} +{{ reserveImport "bytes" }} + +{{ reserveImport "github.com/vektah/gqlparser/v2" }} +{{ reserveImport "github.com/vektah/gqlparser/v2/ast" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql" }} +{{ reserveImport "github.com/99designs/gqlgen/graphql/introspection" }} + +// Add any new functions or any additional code/template functionality here + +{{- range $model := .Interfaces }} + {{ with .Description }} {{.|prefixLines "// "}} {{ end }} + type {{ goModelName .Name }} interface { + {{- if not .OmitCheck }} + {{- range $impl := .Implements }} + Is{{ goModelName $impl }}() + {{- end }} + Is{{ goModelName .Name }}() + {{- end }} + {{- range $field := .Fields }} + {{- with .Description }} + {{.|prefixLines "// "}} + {{- end}} + Get{{ $field.GoName }}() {{ $field.Type | ref }} + {{- end }} + } +{{- end }} + +{{ range $model := .Models }} + {{with .Description }} {{.|prefixLines "// "}} {{end}} + type {{ goModelName .Name }} struct { + {{- range $field := .Fields }} + {{- with .Description }} + {{.|prefixLines "// "}} + {{- end}} + {{ $field.GoName }} {{$field.Type | ref}} `{{$field.Tag}}` + {{- end }} + } + + {{ range .Implements }} + func ({{ goModelName $model.Name }}) Is{{ goModelName . }}() {} + {{- with getInterfaceByName . }} + {{- range .Fields }} + {{- with .Description }} + {{.|prefixLines "// "}} + {{- end}} + {{ generateGetter $model . }} + {{- end }} + {{- end }} + {{ end }} +{{- end}} + +{{ range $enum := .Enums }} + {{ with .Description }} {{.|prefixLines "// "}} {{end}} + type {{ goModelName .Name }} string + const ( + {{- range $value := .Values}} + {{- with .Description}} + {{.|prefixLines "// "}} + {{- end}} + {{ goModelName $enum.Name .Name }} {{ goModelName $enum.Name }} = {{ .Name|quote }} + {{- end }} + ) + + var All{{ goModelName .Name }} = []{{ goModelName .Name }}{ + {{- range $value := .Values}} + {{ goModelName $enum.Name .Name }}, + {{- end }} + } + + func (e {{ goModelName .Name }}) IsValid() bool { + switch e { + case {{ range $index, $element := .Values}}{{if $index}},{{end}}{{ goModelName $enum.Name $element.Name }}{{end}}: + return true + } + return false + } + + func (e {{ goModelName .Name }}) String() string { + return string(e) + } + + func (e *{{ goModelName .Name }}) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = {{ goModelName .Name }}(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid {{ .Name }}", str) + } + return nil + } + + func (e {{ goModelName .Name }}) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) + } + +{{- end }} diff --git a/plugin/modelgen/testdata/gqlgen_custom_model_template.yml b/plugin/modelgen/testdata/gqlgen_custom_model_template.yml new file mode 100644 index 0000000000..ea3d96b5b7 --- /dev/null +++ b/plugin/modelgen/testdata/gqlgen_custom_model_template.yml @@ -0,0 +1,38 @@ +schema: + - "testdata/schema.graphql" + +exec: + filename: out/ignored.go +model: + filename: out/generated.go + model_template: "testdata/customModelTemplate.gotpl" + +models: + ExistingModel: + model: github.com/99designs/gqlgen/plugin/modelgen/out.ExistingModel + ExistingInput: + model: github.com/99designs/gqlgen/plugin/modelgen/out.ExistingInput + ExistingEnum: + model: github.com/99designs/gqlgen/plugin/modelgen/out.ExistingEnum + ExistingInterface: + model: github.com/99designs/gqlgen/plugin/modelgen/out.ExistingInterface + ExistingUnion: + model: github.com/99designs/gqlgen/plugin/modelgen/out.ExistingUnion + ExistingType: + model: github.com/99designs/gqlgen/plugin/modelgen/out.ExistingType + RenameFieldTest: + fields: + badName: + fieldName: GOODnaME + ExtraFieldsTest: + extraFields: + FieldInternalType: + description: "Internal field" + type: github.com/99designs/gqlgen/plugin/modelgen/internal/extrafields.Type + FieldStringPtr: + type: "*string" + FieldInt: + type: "int64" + overrideTags: 'json:"field_int_tag"' + FieldIntSlice: + type: "[]int64" From 60ec0d86847c97cd45c6e431d49b7ccf50efeeb9 Mon Sep 17 00:00:00 2001 From: Douglas Thrift Date: Thu, 27 Jul 2023 06:34:33 -0700 Subject: [PATCH 09/54] Fix plugin template resolution (#2733) - According to the documentation comment for [templates.Options], if the `Template` and `TemplateFS` fields are empty, it `Render` should find the `.gotpl` files from the calling plugin. However, it looks like this is broken since #2262 moved the resolution code to a separate helper function. This results in broken behavior in consumers such as [infiotinc/gqlgenc](https://github.com/infiotinc/gqlgenc) when they use the latest version of `gqlgen` as instead of finding the template from the plugin, the test template from this package is used which outputs only: `this is my test package`. - The cause for this is that `runtime.Caller` was still only skipping one stack level which means that it was finding the `Render` function instead of its caller. [templates.Options]: https://pkg.go.dev/github.com/99designs/gqlgen@v0.17.35/codegen/templates#Options --- codegen/templates/templates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/templates/templates.go b/codegen/templates/templates.go index 332498f878..976527578d 100644 --- a/codegen/templates/templates.go +++ b/codegen/templates/templates.go @@ -172,7 +172,7 @@ func parseTemplates(cfg Options, t *template.Template) (*template.Template, erro fileSystem = cfg.TemplateFS } else { // load path relative to calling source file - _, callerFile, _, _ := runtime.Caller(1) + _, callerFile, _, _ := runtime.Caller(2) rootDir := filepath.Dir(callerFile) fileSystem = os.DirFS(rootDir) } From bd6cfd3108818cd060a06491052c36fb6f5e4be3 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Thu, 27 Jul 2023 14:53:55 -0400 Subject: [PATCH 10/54] release v0.17.36 --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index 39649ff57f..d265a2871d 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 04fff1f298..9c1c257392 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index 06a9c54377..f1e4ba1734 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 6daa854284..dd109c3260 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index acc71de4fc..fe08b7952c 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index 2d66bf9e19..dd23c7a312 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index 4255804608..3b6b81ef6e 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 265b2cdc8d..b78ced18aa 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index 1df3e2f031..47c2288024 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" diff --git a/graphql/version.go b/graphql/version.go index 8c16fdb5b9..be565643f0 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.35-dev" +const Version = "v0.17.36" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index 85b6a59f18..fee5c697e6 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.36 import ( "context" From 0eb95dc4315fc5f74431df03e008283cf9ec0c35 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Thu, 27 Jul 2023 14:54:40 -0400 Subject: [PATCH 11/54] v0.17.36 postrelease bump --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index d265a2871d..2568e9e7c4 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 9c1c257392..70bbc77601 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index f1e4ba1734..cf5f7be192 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index dd109c3260..ed79e492af 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index fe08b7952c..288ce39542 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index dd23c7a312..20a574af4c 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index 3b6b81ef6e..f37815799a 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index b78ced18aa..6dbe081585 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index 47c2288024..dbc098ee93 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" diff --git a/graphql/version.go b/graphql/version.go index be565643f0..cc4e6c903b 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.36" +const Version = "v0.17.36-dev" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index fee5c697e6..b71816a500 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.36 +// Code generated by github.com/99designs/gqlgen version v0.17.36-dev import ( "context" From 790d7a7571865b8b8324557e1a565f40c23217c8 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Fri, 28 Jul 2023 20:15:56 -0700 Subject: [PATCH 12/54] Allow GraphiQL headers to be set when creating the playground handler (#2740) Fixes 99designs/gqlgen#2739 --- graphql/playground/playground.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/graphql/playground/playground.go b/graphql/playground/playground.go index da17ca6201..f3ebabf3d3 100644 --- a/graphql/playground/playground.go +++ b/graphql/playground/playground.go @@ -58,8 +58,13 @@ var page = template.Must(template.New("graphiql").Parse(` const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:'; const subscriptionUrl = wsProto + '//' + location.host + {{.endpoint}}; {{- end}} +{{- if .headers}} + const headers = {{.headers}}; +{{- else}} + const headers = undefined; +{{- end}} - const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl }); + const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl, headers }); ReactDOM.render( React.createElement(GraphiQL, { fetcher: fetcher, @@ -75,11 +80,16 @@ var page = template.Must(template.New("graphiql").Parse(` // Handler responsible for setting up the playground func Handler(title string, endpoint string) http.HandlerFunc { + return HandlerWithHeaders(title, endpoint, nil) +} + +func HandlerWithHeaders(title string, endpoint string, headers map[string]string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "text/html; charset=UTF-8") err := page.Execute(w, map[string]interface{}{ "title": title, "endpoint": endpoint, + "headers": headers, "endpointIsAbsolute": endpointHasScheme(endpoint), "subscriptionEndpoint": getSubscriptionEndpoint(endpoint), "version": "3.0.1", From 2d8673a691deffe6ddd1f4d5f013a52dc91aef91 Mon Sep 17 00:00:00 2001 From: penard-cb <135390596+penard-cb@users.noreply.github.com> Date: Tue, 1 Aug 2023 15:39:05 -0400 Subject: [PATCH 13/54] Add Model references to Interface (#2738) --- plugin/modelgen/models.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugin/modelgen/models.go b/plugin/modelgen/models.go index 23c2e334d9..bbf599d6ed 100644 --- a/plugin/modelgen/models.go +++ b/plugin/modelgen/models.go @@ -52,6 +52,7 @@ type Interface struct { Fields []*Field Implements []string OmitCheck bool + Models []*Object } type Object struct { @@ -200,6 +201,15 @@ func (m *Plugin) MutateConfig(cfg *config.Config) error { cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name)) } for _, it := range b.Interfaces { + // On a given interface we want to keep a reference to all the models that implement it + for _, model := range b.Models { + for _, impl := range model.Implements { + if impl == it.Name { + // If it does, add it to the Interface's Models + it.Models = append(it.Models, model) + } + } + } cfg.Models.Add(it.Name, cfg.Model.ImportPath()+"."+templates.ToGo(it.Name)) } for _, it := range b.Scalars { From d6270e4f4fd951c71ee2a2b997d7098b04e07976 Mon Sep 17 00:00:00 2001 From: leangaurav Date: Wed, 9 Aug 2023 21:15:17 +0530 Subject: [PATCH 14/54] Update subsciptions documentation to correctly close channel (#2753) --- docs/content/recipes/subscriptions.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/content/recipes/subscriptions.md b/docs/content/recipes/subscriptions.md index 5845bb724c..4cf72204e4 100644 --- a/docs/content/recipes/subscriptions.md +++ b/docs/content/recipes/subscriptions.md @@ -121,6 +121,9 @@ func (r *subscriptionResolver) CurrentTime(ctx context.Context) (<-chan *model.T // You can (and probably should) handle your channels in a central place outside of `schema.resolvers.go`. // For this example we'll simply use a Goroutine with a simple loop. go func() { + // Handle deregistration of the channel here. Note the `defer` + defer close(ch) + for { // In our example we'll send the current time every second. time.Sleep(1 * time.Second) @@ -294,6 +297,8 @@ func (r *subscriptionResolver) CurrentTime(ctx context.Context) (<-chan *model.T ch := make(chan *model.Time) go func() { + defer close(ch) + for { time.Sleep(1 * time.Second) fmt.Println("Tick") From 065aea3efa27f0662eb2f62ef2dd131e153009ba Mon Sep 17 00:00:00 2001 From: Mg Pig Date: Sat, 26 Aug 2023 05:52:15 +0800 Subject: [PATCH 15/54] Fix gqlgen truncates tag value with colon (#2759) --- plugin/modelgen/models.go | 10 ++++++---- plugin/modelgen/models_test.go | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/plugin/modelgen/models.go b/plugin/modelgen/models.go index bbf599d6ed..4383d76c92 100644 --- a/plugin/modelgen/models.go +++ b/plugin/modelgen/models.go @@ -568,17 +568,19 @@ func removeDuplicateTags(t string) string { continue } - processed[kv[0]] = true + key := kv[0] + value := strings.Join(kv[1:], ":") + processed[key] = true if len(returnTags) > 0 { returnTags = " " + returnTags } - isContained := containsInvalidSpace(kv[1]) + isContained := containsInvalidSpace(value) if isContained { - panic(fmt.Errorf("tag value should not contain any leading or trailing spaces: %s", kv[1])) + panic(fmt.Errorf("tag value should not contain any leading or trailing spaces: %s", value)) } - returnTags = kv[0] + ":" + kv[1] + returnTags + returnTags = key + ":" + value + returnTags } return returnTags diff --git a/plugin/modelgen/models_test.go b/plugin/modelgen/models_test.go index fa15fa010c..8607615772 100644 --- a/plugin/modelgen/models_test.go +++ b/plugin/modelgen/models_test.go @@ -534,6 +534,22 @@ func TestRemoveDuplicate(t *testing.T) { want: "gorm:\"unique;not null\" json:\"name,name2\"", wantPanic: false, }, + { + name: "Test gorm tag with colon", + args: args{ + t: "gorm:\"type:varchar(63);unique_index\"", + }, + want: "gorm:\"type:varchar(63);unique_index\"", + wantPanic: false, + }, + { + name: "Test mix use of gorm and duplicate json tags with colon", + args: args{ + t: "json:\"name0\" gorm:\"type:varchar(63);unique_index\" json:\"name,name2\"", + }, + want: "gorm:\"type:varchar(63);unique_index\" json:\"name,name2\"", + wantPanic: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 1cde8c3fab65847a6e8d7f423215b786b47c19df Mon Sep 17 00:00:00 2001 From: elad-aharon <137701473+elad-aharon@users.noreply.github.com> Date: Mon, 28 Aug 2023 19:22:02 +0300 Subject: [PATCH 16/54] return internal types in schema introspection (#2773) according to graphql spec: ``` types: return the set of all named types contained within this schema. Any named type which can be found through a field of any introspection type must be included in this set. ``` source: https://github.com/graphql/graphql-spec/blob/main/spec/Section%204%20--%20Introspection.md#the-__schema-type some clients libs (like HotChocolate for C#) depends on this behavior. --- graphql/introspection/schema.go | 4 -- graphql/introspection/schema_test.go | 68 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 graphql/introspection/schema_test.go diff --git a/graphql/introspection/schema.go b/graphql/introspection/schema.go index b7b0ad94e0..897b1a098f 100644 --- a/graphql/introspection/schema.go +++ b/graphql/introspection/schema.go @@ -2,7 +2,6 @@ package introspection import ( "sort" - "strings" "github.com/vektah/gqlparser/v2/ast" ) @@ -22,9 +21,6 @@ func (s *Schema) Types() []Type { typeIndex := map[string]Type{} typeNames := make([]string, 0, len(s.schema.Types)) for _, typ := range s.schema.Types { - if strings.HasPrefix(typ.Name, "__") { - continue - } typeNames = append(typeNames, typ.Name) typeIndex[typ.Name] = *WrapTypeFromDef(s.schema, typ) } diff --git a/graphql/introspection/schema_test.go b/graphql/introspection/schema_test.go new file mode 100644 index 0000000000..92022b1179 --- /dev/null +++ b/graphql/introspection/schema_test.go @@ -0,0 +1,68 @@ +package introspection + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/v2/ast" +) + +func TestSchema(t *testing.T) { + query := &ast.Definition{ + Name: "Query", + Kind: ast.Object, + } + + mutation := &ast.Definition{ + Name: "Mutation", + Kind: ast.Object, + } + + subscription := &ast.Definition{ + Name: "Subscription", + Kind: ast.Object, + } + + directive := &ast.Definition{ + Name: "__Directive", + Kind: ast.Object, + } + + schema := &Schema{ + schema: &ast.Schema{ + Query: query, + Mutation: mutation, + Subscription: subscription, + Types: map[string]*ast.Definition{ + "Query": query, + "Mutation": mutation, + "__Directive": directive, + }, + Description: "test description", + }, + } + + t.Run("description", func(t *testing.T) { + require.EqualValues(t, "test description", *schema.Description()) + }) + + t.Run("query type", func(t *testing.T) { + require.Equal(t, "Query", *schema.QueryType().Name()) + }) + + t.Run("mutation type", func(t *testing.T) { + require.Equal(t, "Mutation", *schema.MutationType().Name()) + }) + + t.Run("subscription type", func(t *testing.T) { + require.Equal(t, "Subscription", *schema.SubscriptionType().Name()) + }) + + t.Run("types", func(t *testing.T) { + types := schema.Types() + require.Len(t, types, 3) + require.Equal(t, "Mutation", *types[0].Name()) + require.Equal(t, "Query", *types[1].Name()) + require.Equal(t, "__Directive", *types[2].Name()) + }) +} From a1ca220477092398efc8e587dd653f5cb967d0e9 Mon Sep 17 00:00:00 2001 From: elad-aharon <137701473+elad-aharon@users.noreply.github.com> Date: Mon, 28 Aug 2023 19:22:13 +0300 Subject: [PATCH 17/54] fix typo in TESTING.md server path (#2774) following TESTING.md instructions, I got an error: "stat ./server/server.go: no such file or directory" server.go path is: integration/server/cmd/integration/server.go --- TESTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TESTING.md b/TESTING.md index b8adadd649..2677b33e48 100644 --- a/TESTING.md +++ b/TESTING.md @@ -25,7 +25,7 @@ Setting up the integration environment is a little tricky: ```bash cd integration go generate ./... -go run ./server/server.go +go run ./server/cmd/integration/server.go ``` in another terminal ```bash From cc4e0ba28375e0ec39c586485fa138c28e5bfcba Mon Sep 17 00:00:00 2001 From: Chris Cerk Date: Tue, 29 Aug 2023 07:11:27 -0400 Subject: [PATCH 18/54] ensure HasOperationContext checks for nil (#2776) --- graphql/context_operation.go | 4 ++-- graphql/context_operation_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/graphql/context_operation.go b/graphql/context_operation.go index 77a42b84b7..3e6a221b0b 100644 --- a/graphql/context_operation.go +++ b/graphql/context_operation.go @@ -73,8 +73,8 @@ func WithOperationContext(ctx context.Context, rc *OperationContext) context.Con // // Some errors can happen outside of an operation, eg json unmarshal errors. func HasOperationContext(ctx context.Context) bool { - _, ok := ctx.Value(operationCtx).(*OperationContext) - return ok + val, ok := ctx.Value(operationCtx).(*OperationContext) + return ok && val != nil } // This is just a convenient wrapper method for CollectFields diff --git a/graphql/context_operation_test.go b/graphql/context_operation_test.go index 4ce374601f..cd4e61e716 100644 --- a/graphql/context_operation_test.go +++ b/graphql/context_operation_test.go @@ -3,11 +3,33 @@ package graphql import ( "context" "testing" + "time" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" ) +// implement context.Context interface +type testGraphRequestContext struct { + opContext *OperationContext +} + +func (t *testGraphRequestContext) Deadline() (deadline time.Time, ok bool) { + return time.Time{}, false +} + +func (t *testGraphRequestContext) Done() <-chan struct{} { + return nil +} + +func (t *testGraphRequestContext) Err() error { + return nil +} + +func (t *testGraphRequestContext) Value(key interface{}) interface{} { + return t.opContext +} + func TestGetOperationContext(t *testing.T) { rc := &OperationContext{} @@ -26,6 +48,15 @@ func TestGetOperationContext(t *testing.T) { GetOperationContext(ctx) }) }) + + t.Run("with nil operation context", func(t *testing.T) { + ctx := &testGraphRequestContext{opContext: nil} + + require.False(t, HasOperationContext(ctx)) + require.Panics(t, func() { + GetOperationContext(ctx) + }) + }) } func TestCollectAllFields(t *testing.T) { From a41f4daad66cb0c102bfa09d7bff5a057d378197 Mon Sep 17 00:00:00 2001 From: Zen Yui Date: Sat, 2 Sep 2023 12:57:34 -0700 Subject: [PATCH 19/54] docs: short-lived loader (#2778) --- docs/content/reference/dataloaders.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/content/reference/dataloaders.md b/docs/content/reference/dataloaders.md index 479b516773..d28be2a8fe 100644 --- a/docs/content/reference/dataloaders.md +++ b/docs/content/reference/dataloaders.md @@ -147,10 +147,11 @@ func NewLoaders(conn *sql.DB) *Loaders { } // Middleware injects data loaders into the context -func Middleware(loaders *Loaders, next http.Handler) http.Handler { +func Middleware(conn *sql.DB, next http.Handler) http.Handler { // return a middleware that injects the loader to the request context return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - r = r.WithContext(context.WithValue(r.Context(), loadersKey, loaders)) + loader := NewLoaders(conn) + r = r.WithContext(context.WithValue(r.Context(), loadersKey, loader)) next.ServeHTTP(w, r) }) } From bee47dcf1f3edb95e7a77e612ea27d85a417b12c Mon Sep 17 00:00:00 2001 From: Viktor Stanchev Date: Mon, 4 Sep 2023 22:40:57 -0400 Subject: [PATCH 20/54] fix flaky test TestSubscriptions (#2779) * fix flaky test TestSubscriptions * update other copy of the test --- codegen/testserver/followschema/subscription_test.go | 11 +++++++++++ codegen/testserver/singlefile/subscription_test.go | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/codegen/testserver/followschema/subscription_test.go b/codegen/testserver/followschema/subscription_test.go index 6126db99ce..c449045190 100644 --- a/codegen/testserver/followschema/subscription_test.go +++ b/codegen/testserver/followschema/subscription_test.go @@ -130,6 +130,9 @@ func TestSubscriptions(t *testing.T) { }) t.Run("will parse init payload", func(t *testing.T) { + runtime.GC() // ensure no go-routines left from preceding tests + initialGoroutineCount := runtime.NumGoroutine() + sub := c.WebsocketWithPayload(`subscription { initPayload }`, map[string]interface{}{ "Authorization": "Bearer of the curse", "number": 32, @@ -155,6 +158,14 @@ func TestSubscriptions(t *testing.T) { require.NoError(t, err) require.Equal(t, "strings = []interface {}{\"hello\", \"world\"}", msg.resp.InitPayload) sub.Close() + + // need a little bit of time for goroutines to settle + start := time.Now() + for time.Since(start).Seconds() < 2 && initialGoroutineCount != runtime.NumGoroutine() { + time.Sleep(5 * time.Millisecond) + } + + require.Equal(t, initialGoroutineCount, runtime.NumGoroutine()) }) t.Run("websocket gets errors", func(t *testing.T) { diff --git a/codegen/testserver/singlefile/subscription_test.go b/codegen/testserver/singlefile/subscription_test.go index 24186e5ebe..567b5acd03 100644 --- a/codegen/testserver/singlefile/subscription_test.go +++ b/codegen/testserver/singlefile/subscription_test.go @@ -130,6 +130,9 @@ func TestSubscriptions(t *testing.T) { }) t.Run("will parse init payload", func(t *testing.T) { + runtime.GC() // ensure no go-routines left from preceding tests + initialGoroutineCount := runtime.NumGoroutine() + sub := c.WebsocketWithPayload(`subscription { initPayload }`, map[string]interface{}{ "Authorization": "Bearer of the curse", "number": 32, @@ -155,6 +158,14 @@ func TestSubscriptions(t *testing.T) { require.NoError(t, err) require.Equal(t, "strings = []interface {}{\"hello\", \"world\"}", msg.resp.InitPayload) sub.Close() + + // need a little bit of time for goroutines to settle + start := time.Now() + for time.Since(start).Seconds() < 2 && initialGoroutineCount != runtime.NumGoroutine() { + time.Sleep(5 * time.Millisecond) + } + + require.Equal(t, initialGoroutineCount, runtime.NumGoroutine()) }) t.Run("websocket gets errors", func(t *testing.T) { From 11bb9b1890fd9e5909f06feba7b2985bf09785c9 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" <12751435+giautm@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:17:31 +0700 Subject: [PATCH 21/54] codegen: add support for `go_build_tags` option in gqlgen.yaml (#2784) * codegen: support go_build_tags option in gqlgen.yaml * chore: added test * docs/content: update config example * chore: more comment --- codegen/config/binder_test.go | 2 +- codegen/config/config.go | 9 ++++- codegen/config/config_test.go | 4 +- codegen/templates/import_test.go | 14 +++---- codegen/templates/templates_test.go | 4 +- docs/content/config.md | 5 +++ internal/code/packages.go | 60 +++++++++++++++++++++-------- internal/code/packages_test.go | 12 +++++- internal/code/testdata/p/p.go | 13 +++++++ internal/imports/prune_test.go | 2 +- 10 files changed, 93 insertions(+), 32 deletions(-) create mode 100644 internal/code/testdata/p/p.go diff --git a/codegen/config/binder_test.go b/codegen/config/binder_test.go index fed3913adb..ae6b3027fb 100644 --- a/codegen/config/binder_test.go +++ b/codegen/config/binder_test.go @@ -187,7 +187,7 @@ func createBinder(cfg Config) (*Binder, *ast.Schema) { Model: []string{"github.com/99designs/gqlgen/graphql.String"}, }, } - cfg.Packages = &code.Packages{} + cfg.Packages = code.NewPackages() cfg.Schema = gqlparser.MustLoadSchema(&ast.Source{Name: "TestAutobinding.schema", Input: ` type Message { id: ID } diff --git a/codegen/config/config.go b/codegen/config/config.go index 8a7205f06b..9f4be075ff 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -26,6 +26,7 @@ type Config struct { Models TypeMap `yaml:"models,omitempty"` StructTag string `yaml:"struct_tag,omitempty"` Directives map[string]DirectiveConfig `yaml:"directives,omitempty"` + GoBuildTags StringList `yaml:"go_build_tags,omitempty"` GoInitialisms GoInitialismsConfig `yaml:"go_initialisms,omitempty"` OmitSliceElementPointers bool `yaml:"omit_slice_element_pointers,omitempty"` OmitGetters bool `yaml:"omit_getters,omitempty"` @@ -211,7 +212,9 @@ func CompleteConfig(config *Config) error { func (c *Config) Init() error { if c.Packages == nil { - c.Packages = &code.Packages{} + c.Packages = code.NewPackages( + code.WithBuildTags(c.GoBuildTags...), + ) } if c.Schema == nil { @@ -671,7 +674,9 @@ func (c *Config) injectBuiltins() { func (c *Config) LoadSchema() error { if c.Packages != nil { - c.Packages = &code.Packages{} + c.Packages = code.NewPackages( + code.WithBuildTags(c.GoBuildTags...), + ) } if err := c.check(); err != nil { diff --git a/codegen/config/config_test.go b/codegen/config/config_test.go index 2ed5d5ac86..68e30d4b95 100644 --- a/codegen/config/config_test.go +++ b/codegen/config/config_test.go @@ -192,7 +192,7 @@ func TestAutobinding(t *testing.T) { "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat", "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/scalars/model", }, - Packages: &code.Packages{}, + Packages: code.NewPackages(), } cfg.Schema = gqlparser.MustLoadSchema(&ast.Source{Name: "TestAutobinding.schema", Input: ` @@ -212,7 +212,7 @@ func TestAutobinding(t *testing.T) { AutoBind: []string{ "../chat", }, - Packages: &code.Packages{}, + Packages: code.NewPackages(), } cfg.Schema = gqlparser.MustLoadSchema(&ast.Source{Name: "TestAutobinding.schema", Input: ` diff --git a/codegen/templates/import_test.go b/codegen/templates/import_test.go index baf88b50ab..483fd5ece8 100644 --- a/codegen/templates/import_test.go +++ b/codegen/templates/import_test.go @@ -20,14 +20,14 @@ func TestImports(t *testing.T) { mismatch := "github.com/99designs/gqlgen/codegen/templates/testdata/pkg_mismatch" t.Run("multiple lookups is ok", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} require.Equal(t, "bar", a.Lookup(aBar)) require.Equal(t, "bar", a.Lookup(aBar)) }) t.Run("lookup by type", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} pkg := types.NewPackage("github.com/99designs/gqlgen/codegen/templates/testdata/b/bar", "bar") typ := types.NewNamed(types.NewTypeName(0, pkg, "Boolean", types.Typ[types.Bool]), types.Typ[types.Bool], nil) @@ -36,7 +36,7 @@ func TestImports(t *testing.T) { }) t.Run("duplicates are decollisioned", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} require.Equal(t, "bar", a.Lookup(aBar)) require.Equal(t, "bar1", a.Lookup(bBar)) @@ -47,7 +47,7 @@ func TestImports(t *testing.T) { }) t.Run("duplicates above 10 are decollisioned", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} for i := 0; i < 100; i++ { cBar := fmt.Sprintf("github.com/99designs/gqlgen/codegen/templates/testdata/%d/bar", i) if i > 0 { @@ -59,13 +59,13 @@ func TestImports(t *testing.T) { }) t.Run("package name defined in code will be used", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} require.Equal(t, "turtles", a.Lookup(mismatch)) }) t.Run("string printing for import block", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} a.Lookup(aBar) a.Lookup(bBar) a.Lookup(mismatch) @@ -80,7 +80,7 @@ turtles "github.com/99designs/gqlgen/codegen/templates/testdata/pkg_mismatch"`, }) t.Run("aliased imports will not collide", func(t *testing.T) { - a := Imports{destDir: wd, packages: &code.Packages{}} + a := Imports{destDir: wd, packages: code.NewPackages()} _, _ = a.Reserve(aBar, "abar") _, _ = a.Reserve(bBar, "bbar") diff --git a/codegen/templates/templates_test.go b/codegen/templates/templates_test.go index 2f57fc9ca1..12ccbb23c1 100644 --- a/codegen/templates/templates_test.go +++ b/codegen/templates/templates_test.go @@ -326,7 +326,7 @@ func TestTemplateOverride(t *testing.T) { } defer f.Close() defer os.RemoveAll(f.Name()) - err = Render(Options{Template: "hello", Filename: f.Name(), Packages: &code.Packages{}}) + err = Render(Options{Template: "hello", Filename: f.Name(), Packages: code.NewPackages()}) if err != nil { t.Fatal(err) } @@ -346,7 +346,7 @@ func TestRenderFS(t *testing.T) { } defer f.Close() defer os.RemoveAll(f.Name()) - err = Render(Options{TemplateFS: templateFS, Filename: f.Name(), Packages: &code.Packages{}}) + err = Render(Options{TemplateFS: templateFS, Filename: f.Name(), Packages: code.NewPackages()}) if err != nil { t.Fatal(err) } diff --git a/docs/content/config.md b/docs/content/config.md index 1d167e2ef0..547c62b8d8 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -84,6 +84,11 @@ resolver: # Optional: set to skip running `go mod tidy` when generating server code # skip_mod_tidy: true +# Optional: set build tags that will be used to load packages +# go_build_tags: +# - private +# - enterprise + # Optional: set to modify the initialisms regarded for Go names # go_initialisms: # replace_defaults: false # if true, the default initialisms will get dropped in favor of the new ones instead of being added diff --git a/internal/code/packages.go b/internal/code/packages.go index 6cb6ef2323..e7f8655aa0 100644 --- a/internal/code/packages.go +++ b/internal/code/packages.go @@ -28,15 +28,37 @@ var mode = packages.NeedName | packages.NeedModule | packages.NeedDeps -// Packages is a wrapper around x/tools/go/packages that maintains a (hopefully prewarmed) cache of packages -// that can be invalidated as writes are made and packages are known to change. -type Packages struct { - packages map[string]*packages.Package - importToName map[string]string - loadErrors []error - - numLoadCalls int // stupid test steam. ignore. - numNameCalls int // stupid test steam. ignore. +type ( + // Packages is a wrapper around x/tools/go/packages that maintains a (hopefully prewarmed) cache of packages + // that can be invalidated as writes are made and packages are known to change. + Packages struct { + packages map[string]*packages.Package + importToName map[string]string + loadErrors []error + buildFlags []string + + numLoadCalls int // stupid test steam. ignore. + numNameCalls int // stupid test steam. ignore. + } + // Option is a function that can be passed to NewPackages to configure the package loader + Option func(p *Packages) +) + +// WithBuildTags adds build tags to the packages.Load call +func WithBuildTags(tags ...string) func(p *Packages) { + return func(p *Packages) { + p.buildFlags = append(p.buildFlags, "-tags", strings.Join(tags, ",")) + } +} + +// NewPackages creates a new packages cache +// It will load all packages in the current module, and any packages that are passed to Load or LoadAll +func NewPackages(opts ...Option) *Packages { + p := &Packages{} + for _, opt := range opts { + opt(p) + } + return p } func (p *Packages) CleanupUserPackages() { @@ -47,8 +69,8 @@ func (p *Packages) CleanupUserPackages() { modInfo = nil } }) - - // Don't cleanup github.com/99designs/gqlgen prefixed packages, they haven't changed and do not need to be reloaded + // Don't cleanup github.com/99designs/gqlgen prefixed packages, + // they haven't changed and do not need to be reloaded if modInfo != nil { var toRemove []string for k := range p.packages { @@ -56,7 +78,6 @@ func (p *Packages) CleanupUserPackages() { toRemove = append(toRemove, k) } } - for _, k := range toRemove { delete(p.packages, k) } @@ -91,7 +112,10 @@ func (p *Packages) LoadAll(importPaths ...string) []*packages.Package { if len(missing) > 0 { p.numLoadCalls++ - pkgs, err := packages.Load(&packages.Config{Mode: mode}, missing...) + pkgs, err := packages.Load(&packages.Config{ + Mode: mode, + BuildFlags: p.buildFlags, + }, missing...) if err != nil { p.loadErrors = append(p.loadErrors, err) } @@ -140,7 +164,10 @@ func (p *Packages) LoadWithTypes(importPath string) *packages.Package { pkg := p.Load(importPath) if pkg == nil || pkg.TypesInfo == nil { p.numLoadCalls++ - pkgs, err := packages.Load(&packages.Config{Mode: mode}, importPath) + pkgs, err := packages.Load(&packages.Config{ + Mode: mode, + BuildFlags: p.buildFlags, + }, importPath) if err != nil { p.loadErrors = append(p.loadErrors, err) return nil @@ -173,7 +200,10 @@ func (p *Packages) NameForPackage(importPath string) string { if pkg == nil { // otherwise do a name only lookup for it but don't put it in the package cache. p.numNameCalls++ - pkgs, err := packages.Load(&packages.Config{Mode: packages.NeedName}, importPath) + pkgs, err := packages.Load(&packages.Config{ + Mode: packages.NeedName, + BuildFlags: p.buildFlags, + }, importPath) if err != nil { p.loadErrors = append(p.loadErrors, err) } else { diff --git a/internal/code/packages_test.go b/internal/code/packages_test.go index 2fbf780c55..1d67419eae 100644 --- a/internal/code/packages_test.go +++ b/internal/code/packages_test.go @@ -38,6 +38,14 @@ func TestPackages(t *testing.T) { require.Equal(t, "b", p.Load("github.com/99designs/gqlgen/internal/code/testdata/b").Name) require.Equal(t, 3, p.numLoadCalls) }) + t.Run("able to load private package with build tags", func(t *testing.T) { + p := initialState(t, WithBuildTags("private")) + p.Evict("github.com/99designs/gqlgen/internal/code/testdata/a") + require.Equal(t, "a", p.Load("github.com/99designs/gqlgen/internal/code/testdata/a").Name) + require.Equal(t, 2, p.numLoadCalls) + require.Equal(t, "p", p.Load("github.com/99designs/gqlgen/internal/code/testdata/p").Name) + require.Equal(t, 3, p.numLoadCalls) + }) } func TestNameForPackage(t *testing.T) { @@ -50,8 +58,8 @@ func TestNameForPackage(t *testing.T) { assert.Equal(t, "github_com", p.NameForPackage("github.com")) } -func initialState(t *testing.T) *Packages { - p := &Packages{} +func initialState(t *testing.T, opts ...Option) *Packages { + p := NewPackages(opts...) pkgs := p.LoadAll( "github.com/99designs/gqlgen/internal/code/testdata/a", "github.com/99designs/gqlgen/internal/code/testdata/b", diff --git a/internal/code/testdata/p/p.go b/internal/code/testdata/p/p.go new file mode 100644 index 0000000000..bf516e9813 --- /dev/null +++ b/internal/code/testdata/p/p.go @@ -0,0 +1,13 @@ +//go:build private +// +build private + +// This file is excluded from the build unless the "private" build tag is set. +// This is used to test loading private packages. +// See internal/code/packages_test.go for more details. +package p + +import ( + "github.com/99designs/gqlgen/internal/code/testdata/b" +) + +var P = b.C + " P" diff --git a/internal/imports/prune_test.go b/internal/imports/prune_test.go index 15af13dcd2..0006aec9ac 100644 --- a/internal/imports/prune_test.go +++ b/internal/imports/prune_test.go @@ -12,7 +12,7 @@ import ( func TestPrune(t *testing.T) { // prime the packages cache so that it's not considered uninitialized - b, err := Prune("testdata/unused.go", mustReadFile("testdata/unused.go"), &code.Packages{}) + b, err := Prune("testdata/unused.go", mustReadFile("testdata/unused.go"), code.NewPackages()) require.NoError(t, err) require.Equal(t, strings.ReplaceAll(string(mustReadFile("testdata/unused.expected.go")), "\r\n", "\n"), string(b)) } From fa4711801c59d27db887a50e1f8393006268194e Mon Sep 17 00:00:00 2001 From: "Roman A. Grigorovich" Date: Fri, 8 Sep 2023 15:12:15 +0300 Subject: [PATCH 22/54] ForceGenerate parameter to @goModel added. (#2780) * ForceGenerate parameter to @goModel added. * forceGenerate to docs added --------- Co-authored-by: Roman A. Grigorovich --- codegen/config/config.go | 23 +++++++++++++++++++++-- docs/content/config.md | 3 ++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/codegen/config/config.go b/codegen/config/config.go index 9f4be075ff..ddf10ac21d 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -284,6 +284,7 @@ func (c *Config) injectTypesFromSchema() error { c.Models.Add(schemaType.Name, mv.(string)) } } + if ma := bd.Arguments.ForName("models"); ma != nil { if mvs, err := ma.Value.Value(nil); err == nil { for _, mv := range mvs.([]interface{}) { @@ -291,6 +292,12 @@ func (c *Config) injectTypesFromSchema() error { } } } + + if fg := bd.Arguments.ForName("forceGenerate"); fg != nil { + if mv, err := fg.Value.Value(nil); err == nil { + c.Models.ForceGenerate(schemaType.Name, mv.(bool)) + } + } } if schemaType.Kind == ast.Object || schemaType.Kind == ast.InputObject { @@ -332,8 +339,9 @@ func (c *Config) injectTypesFromSchema() error { } type TypeMapEntry struct { - Model StringList `yaml:"model"` - Fields map[string]TypeMapField `yaml:"fields,omitempty"` + Model StringList `yaml:"model,omitempty"` + ForceGenerate bool `yaml:"forceGenerate,omitempty"` + Fields map[string]TypeMapField `yaml:"fields,omitempty"` // Key is the Go name of the field. ExtraFields map[string]ModelExtraField `yaml:"extraFields,omitempty"` @@ -532,6 +540,12 @@ func (tm TypeMap) Add(name string, goType string) { tm[name] = modelCfg } +func (tm TypeMap) ForceGenerate(name string, forceGenerate bool) { + modelCfg := tm[name] + modelCfg.ForceGenerate = forceGenerate + tm[name] = modelCfg +} + type DirectiveConfig struct { SkipRuntime bool `yaml:"skip_runtime"` } @@ -590,6 +604,11 @@ func (c *Config) autobind() error { continue } + if c.Models[t.Name].ForceGenerate { + delete(c.Models, t.Name) + continue + } + for i, p := range ps { if p == nil || p.Module == nil { return fmt.Errorf("unable to load %s - make sure you're using an import path to a package that exists", c.AutoBind[i]) diff --git a/docs/content/config.md b/docs/content/config.md index 547c62b8d8..65e5e6fd56 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -132,12 +132,13 @@ To start using them you first need to define them: directive @goModel( model: String models: [String!] + forceGenerate: Boolean ) on OBJECT | INPUT_OBJECT | SCALAR | ENUM | INTERFACE | UNION directive @goField( forceResolver: Boolean name: String - omittable: Boolean + omittable: Boolean ) on INPUT_FIELD_DEFINITION | FIELD_DEFINITION directive @goTag( From 153ec470d993a39c1656fc45432740f1d3dd10ea Mon Sep 17 00:00:00 2001 From: MikeWang Date: Fri, 8 Sep 2023 20:36:30 +0800 Subject: [PATCH 23/54] add uuid type (#2751) * add uuid type * add uuid example * add uuid scalar doc * strconv.Quote * Apply suggestions from code review * fix * Adjust documentation to match PR #2749 Signed-off-by: Steve Coffman --------- Signed-off-by: Steve Coffman Co-authored-by: Steve Coffman Co-authored-by: Steve Coffman --- _examples/go.mod | 3 +- _examples/go.sum | 2 + _examples/uuid/gqlgen.yml | 90 + _examples/uuid/graph/generated.go | 3700 ++++++++++++++++++++++ _examples/uuid/graph/model/models_gen.go | 20 + _examples/uuid/graph/resolver.go | 7 + _examples/uuid/graph/schema.graphqls | 27 + _examples/uuid/graph/schema.resolvers.go | 39 + _examples/uuid/server.go | 28 + docs/content/config.md | 3 + docs/content/reference/scalars.md | 45 +- go.mod | 1 + go.sum | 2 + graphql/uuid.go | 26 + graphql/uuid_test.go | 56 + 15 files changed, 4037 insertions(+), 12 deletions(-) create mode 100644 _examples/uuid/gqlgen.yml create mode 100644 _examples/uuid/graph/generated.go create mode 100644 _examples/uuid/graph/model/models_gen.go create mode 100644 _examples/uuid/graph/resolver.go create mode 100644 _examples/uuid/graph/schema.graphqls create mode 100644 _examples/uuid/graph/schema.resolvers.go create mode 100644 _examples/uuid/server.go create mode 100644 graphql/uuid.go create mode 100644 graphql/uuid_test.go diff --git a/_examples/go.mod b/_examples/go.mod index d26124f0ab..7fff38167d 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -5,7 +5,8 @@ go 1.18 replace github.com/99designs/gqlgen => ../ require ( - github.com/99designs/gqlgen v0.17.32 + github.com/99designs/gqlgen v0.17.36 + github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.5.0 github.com/mitchellh/mapstructure v1.5.0 github.com/opentracing/opentracing-go v1.2.0 diff --git a/_examples/go.sum b/_examples/go.sum index 8e76230a20..4b69acaff2 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -12,6 +12,8 @@ github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= diff --git a/_examples/uuid/gqlgen.yml b/_examples/uuid/gqlgen.yml new file mode 100644 index 0000000000..33c3d09ddd --- /dev/null +++ b/_examples/uuid/gqlgen.yml @@ -0,0 +1,90 @@ +# Where are all the schema files located? globs are supported eg src/**/*.graphqls +schema: + - graph/*.graphqls + +# Where should the generated server code go? +exec: + filename: graph/generated.go + package: graph + +# Uncomment to enable federation +# federation: +# filename: graph/federation.go +# package: graph + +# Where should any generated models go? +model: + filename: graph/model/models_gen.go + package: model + +# Where should the resolver implementations go? +resolver: + layout: follow-schema + dir: graph + package: graph + filename_template: "{name}.resolvers.go" + # Optional: turn on to not generate template comments above resolvers + # omit_template_comment: false + +# Optional: turn on use ` + "`" + `gqlgen:"fieldName"` + "`" + ` tags in your models +# struct_tag: json + +# Optional: turn on to use []Thing instead of []*Thing +# omit_slice_element_pointers: false + +# Optional: turn on to omit Is() methods to interface and unions +# omit_interface_checks : true + +# Optional: turn on to skip generation of ComplexityRoot struct content and Complexity function +# omit_complexity: false + +# Optional: turn on to not generate any file notice comments in generated files +# omit_gqlgen_file_notice: false + +# Optional: turn on to exclude the gqlgen version in the generated file notice. No effect if `omit_gqlgen_file_notice` is true. +# omit_gqlgen_version_in_file_notice: false + +# Optional: turn off to make struct-type struct fields not use pointers +# e.g. type Thing struct { FieldA OtherThing } instead of { FieldA *OtherThing } +# struct_fields_always_pointers: true + +# Optional: turn off to make resolvers return values instead of pointers for structs +# resolvers_always_return_pointers: true + +# Optional: turn on to return pointers instead of values in unmarshalInput +# return_pointers_in_unmarshalinput: false + +# Optional: wrap nullable input fields with Omittable +# nullable_input_omittable: true + +# Optional: set to speed up generation time by not performing a final validation pass. +# skip_validation: true + +# Optional: set to skip running `go mod tidy` when generating server code +# skip_mod_tidy: true + +# 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/99designs/gqlgen/_examples/uuid/graph/model" + +# This section declares type mapping between the GraphQL and go type systems +# +# The first line in each type will be used as defaults for resolver arguments and +# modelgen, the others will be allowed when binding to fields. Configure them to +# your liking +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.ID + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + Int: + model: + - github.com/99designs/gqlgen/graphql.Int + - github.com/99designs/gqlgen/graphql.Int64 + - github.com/99designs/gqlgen/graphql.Int32 + UUID: + model: + - github.com/99designs/gqlgen/graphql.UUID diff --git a/_examples/uuid/graph/generated.go b/_examples/uuid/graph/generated.go new file mode 100644 index 0000000000..57b2c363a8 --- /dev/null +++ b/_examples/uuid/graph/generated.go @@ -0,0 +1,3700 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package graph + +import ( + "bytes" + "context" + "embed" + "errors" + "fmt" + "strconv" + "sync" + "sync/atomic" + + "github.com/99designs/gqlgen/_examples/uuid/graph/model" + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/introspection" + "github.com/google/uuid" + gqlparser "github.com/vektah/gqlparser/v2" + "github.com/vektah/gqlparser/v2/ast" +) + +// region ************************** generated!.gotpl ************************** + +// NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. +func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { + return &executableSchema{ + resolvers: cfg.Resolvers, + directives: cfg.Directives, + complexity: cfg.Complexity, + } +} + +type Config struct { + Resolvers ResolverRoot + Directives DirectiveRoot + Complexity ComplexityRoot +} + +type ResolverRoot interface { + Mutation() MutationResolver + Query() QueryResolver +} + +type DirectiveRoot struct { +} + +type ComplexityRoot struct { + Mutation struct { + CreateTodo func(childComplexity int, input model.NewTodo) int + } + + Query struct { + Todos func(childComplexity int) int + } + + Todo struct { + Done func(childComplexity int) int + ID func(childComplexity int) int + Text func(childComplexity int) int + UID func(childComplexity int) int + } +} + +type MutationResolver interface { + CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) +} +type QueryResolver interface { + Todos(ctx context.Context) ([]*model.Todo, error) +} + +type executableSchema struct { + resolvers ResolverRoot + directives DirectiveRoot + complexity ComplexityRoot +} + +func (e *executableSchema) Schema() *ast.Schema { + return parsedSchema +} + +func (e *executableSchema) Complexity(typeName, field string, childComplexity int, rawArgs map[string]interface{}) (int, bool) { + ec := executionContext{nil, e, 0, 0, nil} + _ = ec + switch typeName + "." + field { + + case "Mutation.createTodo": + if e.complexity.Mutation.CreateTodo == nil { + break + } + + args, err := ec.field_Mutation_createTodo_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateTodo(childComplexity, args["input"].(model.NewTodo)), true + + case "Query.todos": + if e.complexity.Query.Todos == nil { + break + } + + return e.complexity.Query.Todos(childComplexity), true + + case "Todo.done": + if e.complexity.Todo.Done == nil { + break + } + + return e.complexity.Todo.Done(childComplexity), true + + case "Todo.id": + if e.complexity.Todo.ID == nil { + break + } + + return e.complexity.Todo.ID(childComplexity), true + + case "Todo.text": + if e.complexity.Todo.Text == nil { + break + } + + return e.complexity.Todo.Text(childComplexity), true + + case "Todo.uid": + if e.complexity.Todo.UID == nil { + break + } + + return e.complexity.Todo.UID(childComplexity), true + + } + return 0, false +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e, 0, 0, make(chan graphql.DeferredResult)} + inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputNewTodo, + ) + first := true + + switch rc.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + 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 + } + } + var buf bytes.Buffer + data.MarshalGQL(&buf) + 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 { + if !first { + return nil + } + first = false + ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap) + data := ec._Mutation(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + + default: + return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) + } +} + +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) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapSchema(parsedSchema), nil +} + +func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { + if ec.DisableIntrospection { + return nil, errors.New("introspection disabled") + } + return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil +} + +//go:embed "schema.graphqls" +var sourcesFS embed.FS + +func sourceData(filename string) string { + data, err := sourcesFS.ReadFile(filename) + if err != nil { + panic(fmt.Sprintf("codegen problem: %s not available", filename)) + } + return string(data) +} + +var sources = []*ast.Source{ + {Name: "schema.graphqls", Input: sourceData("schema.graphqls"), BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +func (ec *executionContext) field_Mutation_createTodo_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 model.NewTodo + if tmp, ok := rawArgs["input"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("input")) + arg0, err = ec.unmarshalNNewTodo2githubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐNewTodo(ctx, tmp) + if err != nil { + return nil, err + } + } + args["input"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query___type_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["name"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) + if err != nil { + return nil, err + } + } + args["name"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_enumValues_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 bool + if tmp, ok := rawArgs["includeDeprecated"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("includeDeprecated")) + arg0, err = ec.unmarshalOBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = arg0 + return args, nil +} + +// endregion ***************************** args.gotpl ***************************** + +// region ************************** directives.gotpl ************************** + +// endregion ************************** directives.gotpl ************************** + +// region **************************** field.gotpl ***************************** + +func (ec *executionContext) _Mutation_createTodo(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Mutation_createTodo(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.Mutation().CreateTodo(rctx, fc.Args["input"].(model.NewTodo)) + }) + 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.(*model.Todo) + fc.Result = res + return ec.marshalNTodo2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐTodo(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Mutation_createTodo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Mutation", + 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_Todo_id(ctx, field) + case "text": + return ec.fieldContext_Todo_text(ctx, field) + case "done": + return ec.fieldContext_Todo_done(ctx, field) + case "uid": + return ec.fieldContext_Todo_uid(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Todo", 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_Mutation_createTodo_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_todos(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().Todos(rctx) + }) + 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.([]*model.Todo) + fc.Result = res + return ec.marshalNTodo2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐTodoᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_todos(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 "id": + return ec.fieldContext_Todo_id(ctx, field) + case "text": + return ec.fieldContext_Todo_text(ctx, field) + case "done": + return ec.fieldContext_Todo_done(ctx, field) + case "uid": + return ec.fieldContext_Todo_uid(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Todo", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query___type(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.introspectType(fc.Args["name"].(string)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query___type(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) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", 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___type_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query___schema(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.introspectSchema() + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Schema) + fc.Result = res + return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query___schema(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) { + switch field.Name { + case "description": + return ec.fieldContext___Schema_description(ctx, field) + case "types": + return ec.fieldContext___Schema_types(ctx, field) + case "queryType": + return ec.fieldContext___Schema_queryType(ctx, field) + case "mutationType": + return ec.fieldContext___Schema_mutationType(ctx, field) + case "subscriptionType": + return ec.fieldContext___Schema_subscriptionType(ctx, field) + case "directives": + return ec.fieldContext___Schema_directives(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Schema", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Todo_id(ctx context.Context, field graphql.CollectedField, obj *model.Todo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Todo_id(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.ID, 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.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Todo_id(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Todo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Todo_text(ctx context.Context, field graphql.CollectedField, obj *model.Todo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Todo_text(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.Text, 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_Todo_text(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Todo", + 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) _Todo_done(ctx context.Context, field graphql.CollectedField, obj *model.Todo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Todo_done(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.Done, 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_Todo_done(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Todo", + 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) _Todo_uid(ctx context.Context, field graphql.CollectedField, obj *model.Todo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Todo_uid(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.UID, 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.(uuid.UUID) + fc.Result = res + return ec.marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Todo_uid(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Todo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type UUID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_name(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.Name, 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___Directive_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + 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) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_description(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.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: true, + 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) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_locations(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.Locations, 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.marshalN__DirectiveLocation2ᚕstringᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_locations(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type __DirectiveLocation does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_args(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.Args, 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.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Directive_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Directive_isRepeatable(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.IsRepeatable, 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___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Directive", + 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) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_name(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.Name, 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___EnumValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + 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) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_description(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.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + 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) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_isDeprecated(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.IsDeprecated(), 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___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + 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) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___EnumValue_deprecationReason(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.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + IsMethod: true, + 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) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_name(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.Name, 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___Field_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + 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) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_description(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.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + 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) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_args(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.Args, 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.([]introspection.InputValue) + fc.Result = res + return ec.marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_args(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_type(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.Type, 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.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_isDeprecated(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.IsDeprecated(), 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___Field_isDeprecated(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + 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) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Field_deprecationReason(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.DeprecationReason(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Field_deprecationReason(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Field", + Field: field, + IsMethod: true, + 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) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_name(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.Name, 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___InputValue_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + 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) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_description(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.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: true, + 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) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_type(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.Type, 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.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___InputValue_defaultValue(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.DefaultValue, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__InputValue", + 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) ___Schema_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_description(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.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + 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) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_types(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.Types(), 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.([]introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_types(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_queryType(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.QueryType(), 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.(*introspection.Type) + fc.Result = res + return ec.marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_queryType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_mutationType(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.MutationType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_mutationType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_subscriptionType(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.SubscriptionType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Schema_directives(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.Directives(), 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.([]introspection.Directive) + fc.Result = res + return ec.marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Schema_directives(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Schema", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Directive_name(ctx, field) + case "description": + return ec.fieldContext___Directive_description(ctx, field) + case "locations": + return ec.fieldContext___Directive_locations(ctx, field) + case "args": + return ec.fieldContext___Directive_args(ctx, field) + case "isRepeatable": + return ec.fieldContext___Directive_isRepeatable(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Directive", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_kind(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.Kind(), 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.marshalN__TypeKind2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_kind(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type __TypeKind does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_name(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.Name(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_name(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + 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) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_description(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.Description(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_description(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + 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) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_fields(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.Fields(fc.Args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Field) + fc.Result = res + return ec.marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_fields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___Field_name(ctx, field) + case "description": + return ec.fieldContext___Field_description(ctx, field) + case "args": + return ec.fieldContext___Field_args(ctx, field) + case "type": + return ec.fieldContext___Field_type(ctx, field) + case "isDeprecated": + return ec.fieldContext___Field_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___Field_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Field", 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___Type_fields_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_interfaces(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.Interfaces(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_interfaces(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_possibleTypes(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.PossibleTypes(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_possibleTypes(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_enumValues(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.EnumValues(fc.Args["includeDeprecated"].(bool)), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.EnumValue) + fc.Result = res + return ec.marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_enumValues(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___EnumValue_name(ctx, field) + case "description": + return ec.fieldContext___EnumValue_description(ctx, field) + case "isDeprecated": + return ec.fieldContext___EnumValue_isDeprecated(ctx, field) + case "deprecationReason": + return ec.fieldContext___EnumValue_deprecationReason(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __EnumValue", 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___Type_enumValues_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_inputFields(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.InputFields(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]introspection.InputValue) + fc.Result = res + return ec.marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_inputFields(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "name": + return ec.fieldContext___InputValue_name(ctx, field) + case "description": + return ec.fieldContext___InputValue_description(ctx, field) + case "type": + return ec.fieldContext___InputValue_type(ctx, field) + case "defaultValue": + return ec.fieldContext___InputValue_defaultValue(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __InputValue", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_ofType(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.OfType(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*introspection.Type) + fc.Result = res + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_ofType(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "kind": + return ec.fieldContext___Type_kind(ctx, field) + case "name": + return ec.fieldContext___Type_name(ctx, field) + case "description": + return ec.fieldContext___Type_description(ctx, field) + case "fields": + return ec.fieldContext___Type_fields(ctx, field) + case "interfaces": + return ec.fieldContext___Type_interfaces(ctx, field) + case "possibleTypes": + return ec.fieldContext___Type_possibleTypes(ctx, field) + case "enumValues": + return ec.fieldContext___Type_enumValues(ctx, field) + case "inputFields": + return ec.fieldContext___Type_inputFields(ctx, field) + case "ofType": + return ec.fieldContext___Type_ofType(ctx, field) + case "specifiedByURL": + return ec.fieldContext___Type_specifiedByURL(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type __Type", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) ___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + fc, err := ec.fieldContext___Type_specifiedByURL(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.SpecifiedByURL(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext___Type_specifiedByURL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "__Type", + Field: field, + IsMethod: true, + 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 +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputNewTodo(ctx context.Context, obj interface{}) (model.NewTodo, error) { + var it model.NewTodo + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"text", "userId", "uid"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "text": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("text")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.Text = data + case "userId": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userId")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it.UserID = data + case "uid": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("uid")) + data, err := ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v) + if err != nil { + return it, err + } + it.UID = data + } + } + + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + 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("Mutation") + case "createTodo": + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_createTodo(ctx, field) + }) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +var queryImplementors = []string{"Query"} + +func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, queryImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Query", + }) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + 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("Query") + case "todos": + field := field + + 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)) + } + }() + res = ec._Query_todos(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, + func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + } + + 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(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 +} + +var todoImplementors = []string{"Todo"} + +func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj *model.Todo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, todoImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Todo") + case "id": + out.Values[i] = ec._Todo_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "text": + out.Values[i] = ec._Todo_text(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "done": + out.Values[i] = ec._Todo_done(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "uid": + out.Values[i] = ec._Todo_uid(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +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) + 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 { + 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 { + out.Invalids++ + } + case "args": + out.Values[i] = ec.___Directive_args(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "isRepeatable": + out.Values[i] = ec.___Directive_isRepeatable(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +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) + 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 { + 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 { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___EnumValue_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +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) + 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 { + 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 { + out.Invalids++ + } + case "type": + out.Values[i] = ec.___Field_type(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "isDeprecated": + out.Values[i] = ec.___Field_isDeprecated(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "deprecationReason": + out.Values[i] = ec.___Field_deprecationReason(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +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) + 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 { + 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 { + out.Invalids++ + } + case "defaultValue": + out.Values[i] = ec.___InputValue_defaultValue(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +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) + 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 { + out.Invalids++ + } + case "queryType": + out.Values[i] = ec.___Schema_queryType(ctx, field, obj) + if out.Values[i] == graphql.Null { + 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 { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + +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) + 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 { + 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(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 +} + +// endregion **************************** object.gotpl **************************** + +// region ***************************** type.gotpl ***************************** + +func (ec *executionContext) unmarshalNBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(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) unmarshalNID2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalID(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) unmarshalNNewTodo2githubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐNewTodo(ctx context.Context, v interface{}) (model.NewTodo, error) { + res, err := ec.unmarshalInputNewTodo(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) marshalNTodo2githubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐTodo(ctx context.Context, sel ast.SelectionSet, v model.Todo) graphql.Marshaler { + return ec._Todo(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTodo2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐTodoᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Todo) 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.marshalNTodo2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐTodo(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNTodo2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋ_examplesᚋuuidᚋgraphᚋmodelᚐTodo(ctx context.Context, sel ast.SelectionSet, v *model.Todo) 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 + } + return ec._Todo(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, v interface{}) (uuid.UUID, error) { + res, err := graphql.UnmarshalUUID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, sel ast.SelectionSet, v uuid.UUID) graphql.Marshaler { + res := graphql.MarshalUUID(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) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { + return ec.___Directive(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Directive2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirectiveᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Directive) 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.marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__DirectiveLocation2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalN__DirectiveLocation2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalN__DirectiveLocation2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) 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.marshalN__DirectiveLocation2string(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx context.Context, sel ast.SelectionSet, v introspection.EnumValue) graphql.Marshaler { + return ec.___EnumValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx context.Context, sel ast.SelectionSet, v introspection.Field) graphql.Marshaler { + return ec.___Field(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx context.Context, sel ast.SelectionSet, v introspection.InputValue) graphql.Marshaler { + return ec.___InputValue(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) 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.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v introspection.Type) graphql.Marshaler { + return ec.___Type(ctx, sel, &v) +} + +func (ec *executionContext) marshalN__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) 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.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalN__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) 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 + } + return ec.___Type(ctx, sel, v) +} + +func (ec *executionContext) unmarshalN__TypeKind2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { + res, err := graphql.UnmarshalBoolean(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2bool(ctx context.Context, sel ast.SelectionSet, v bool) graphql.Marshaler { + res := graphql.MarshalBoolean(v) + return res +} + +func (ec *executionContext) unmarshalOBoolean2ᚖbool(ctx context.Context, v interface{}) (*bool, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalBoolean(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast.SelectionSet, v *bool) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalBoolean(*v) + return res +} + +func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalString(*v) + return res +} + +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 + } + 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.marshalN__EnumValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Field2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐFieldᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Field) graphql.Marshaler { + if v == nil { + return graphql.Null + } + 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.marshalN__Field2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐField(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__InputValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.InputValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + 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.marshalN__InputValue2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐInputValue(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx context.Context, sel ast.SelectionSet, v *introspection.Schema) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Schema(ctx, sel, v) +} + +func (ec *executionContext) marshalO__Type2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐTypeᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + 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.marshalN__Type2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx context.Context, sel ast.SelectionSet, v *introspection.Type) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec.___Type(ctx, sel, v) +} + +// endregion ***************************** type.gotpl ***************************** diff --git a/_examples/uuid/graph/model/models_gen.go b/_examples/uuid/graph/model/models_gen.go new file mode 100644 index 0000000000..a4dc0a3239 --- /dev/null +++ b/_examples/uuid/graph/model/models_gen.go @@ -0,0 +1,20 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package model + +import ( + "github.com/google/uuid" +) + +type NewTodo struct { + Text string `json:"text"` + UserID string `json:"userId"` + UID uuid.UUID `json:"uid"` +} + +type Todo struct { + ID string `json:"id"` + Text string `json:"text"` + Done bool `json:"done"` + UID uuid.UUID `json:"uid"` +} diff --git a/_examples/uuid/graph/resolver.go b/_examples/uuid/graph/resolver.go new file mode 100644 index 0000000000..a25c09c619 --- /dev/null +++ b/_examples/uuid/graph/resolver.go @@ -0,0 +1,7 @@ +package graph + +// This file will not be regenerated automatically. +// +// It serves as dependency injection for your app, add any dependencies you require here. + +type Resolver struct{} diff --git a/_examples/uuid/graph/schema.graphqls b/_examples/uuid/graph/schema.graphqls new file mode 100644 index 0000000000..074282574f --- /dev/null +++ b/_examples/uuid/graph/schema.graphqls @@ -0,0 +1,27 @@ +# GraphQL schema example +# +# https://gqlgen.com/getting-started/ + +type Todo { + id: ID! + text: String! + done: Boolean! + uid: UUID! +} + + +type Query { + todos: [Todo!]! +} + +input NewTodo { + text: String! + userId: String! + uid: UUID! +} + +type Mutation { + createTodo(input: NewTodo!): Todo! +} + +scalar UUID diff --git a/_examples/uuid/graph/schema.resolvers.go b/_examples/uuid/graph/schema.resolvers.go new file mode 100644 index 0000000000..1fd92e5290 --- /dev/null +++ b/_examples/uuid/graph/schema.resolvers.go @@ -0,0 +1,39 @@ +package graph + +// 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.36 + +import ( + "context" + + "github.com/99designs/gqlgen/_examples/uuid/graph/model" + "github.com/google/uuid" +) + +// CreateTodo is the resolver for the createTodo field. +func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { + return &model.Todo{ + ID: input.UserID, + Text: input.Text, + Done: true, + UID: input.UID, + }, nil +} + +// Todos is the resolver for the todos field. +func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) { + return []*model.Todo{ + {ID: "1", Text: "hello", Done: true, UID: uuid.New()}, + {ID: "2", Text: "world", Done: false, UID: uuid.New()}, + }, nil +} + +// Mutation returns MutationResolver implementation. +func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } + +// Query returns QueryResolver implementation. +func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } + +type mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } diff --git a/_examples/uuid/server.go b/_examples/uuid/server.go new file mode 100644 index 0000000000..cb10a9dfa8 --- /dev/null +++ b/_examples/uuid/server.go @@ -0,0 +1,28 @@ +package main + +import ( + "log" + "net/http" + "os" + + "github.com/99designs/gqlgen/_examples/uuid/graph" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" +) + +const defaultPort = "8080" + +func main() { + port := os.Getenv("PORT") + if port == "" { + port = defaultPort + } + + srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}})) + + http.Handle("/", playground.Handler("GraphQL playground", "/query")) + http.Handle("/query", srv) + + log.Printf("connect to http://localhost:%s/ for GraphQL playground", port) + log.Fatal(http.ListenAndServe(":"+port, nil)) +} diff --git a/docs/content/config.md b/docs/content/config.md index 65e5e6fd56..26dba6fed8 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -118,6 +118,9 @@ models: - github.com/99designs/gqlgen/graphql.Int - github.com/99designs/gqlgen/graphql.Int64 - github.com/99designs/gqlgen/graphql.Int32 + UUID: + model: + - github.com/99designs/gqlgen/graphql.UUID ``` Everything has defaults, so add things as you need. diff --git a/docs/content/reference/scalars.md b/docs/content/reference/scalars.md index 8241090b6a..abec39910c 100644 --- a/docs/content/reference/scalars.md +++ b/docs/content/reference/scalars.md @@ -7,7 +7,8 @@ menu: { main: { parent: "reference", weight: 10 } } ## Built-in helpers -gqlgen ships with some built-in helpers for common custom scalar use-cases, `Time`, `Any`, `Upload` and `Map`. Adding any of these to a schema will automatically add the marshalling behaviour to Go types. +gqlgen ships with some built-in helpers for common custom scalar use-cases, `Time`, `Any`, `Upload` and `Map`. +Adding any of these to a schema will automatically add the marshalling behaviour to Go types. ### Time @@ -15,7 +16,27 @@ gqlgen ships with some built-in helpers for common custom scalar use-cases, `Tim scalar Time ``` -Maps a `Time` GraphQL scalar to a Go `time.Time` struct. This scalar adheres to the [time.RFC3339Nano](https://pkg.go.dev/time#pkg-constants) format. +Maps a `Time` GraphQL scalar to a Go `time.Time` struct. +This scalar adheres to the [time.RFC3339Nano](https://pkg.go.dev/time#pkg-constants) format. + +### Universally Unique Identifier (UUID) + +```graphql +scalar UUID +``` +This maps a `UUID` scalar value to a `uuid.UUID` type. + +If you add to gqlgen.yml: +```yaml +models: + UUID: + model: + - github.com/99designs/gqlgen/graphql.UUID +``` + +And then add `scalar UUID` to `schema.graphql` + +See the _examples/uuid package for more examples. ### Map @@ -131,7 +152,7 @@ func ParseLength(string) (Length, error) func (l Length) FormatContext(ctx context.Context) (string, error) ``` -and then wire up the type in .gqlgen.yml or via directives like normal: +and then wire up the type in `.gqlgen.yml` or via directives like normal: ```yaml models: @@ -141,8 +162,8 @@ models: ## Custom scalars with third party types -Sometimes you are unable to add add methods to a type - perhaps you don't own the type, or it is part of the standard -library (eg string or time.Time). To support this we can build an external marshaler: +Sometimes you are unable to add add methods to a type — perhaps you don't own the type, or it is part of the standard +library (eg `string` or `time.Time`). To support this we can build an external marshaler: ```go package mypkg @@ -180,7 +201,7 @@ func UnmarshalMyCustomBooleanScalar(v interface{}) (bool, error) { } ``` -Then in .gqlgen.yml point to the name without the Marshal|Unmarshal in front: +Then in `.gqlgen.yml` point to the name without the Marshal|Unmarshal in front: ```yaml models: @@ -188,10 +209,10 @@ models: model: github.com/me/mypkg.MyCustomBooleanScalar ``` -**Note:** you also can un/marshal to pointer types via this approach, simply accept a pointer in your +**Note:** You also can (un)marshal to pointer types via this approach, simply accept a pointer in your `Marshal...` func and return one in your `Unmarshal...` func. -**Note:** you can also un/marshal with a context by having your custom marshal function return a +**Note:** You can also (un)marshal with a context by having your custom marshal function return a `graphql.ContextMarshaler` _and_ your unmarshal function take a `context.Context` as the first argument. See the [_examples/scalars](https://github.com/99designs/gqlgen/tree/master/_examples/scalars) package for more examples. @@ -199,7 +220,7 @@ See the [_examples/scalars](https://github.com/99designs/gqlgen/tree/master/_exa ## Marshaling/Unmarshaling Errors The errors that occur as part of custom scalar marshaling/unmarshaling will return a full path to the field. -For example, given the following schema ... +For example, given the following schema: ```graphql extend type Mutation{ @@ -213,6 +234,7 @@ input UserInput { } scalar Email + input ContactDetailsInput { email: Email! } @@ -221,7 +243,6 @@ input ContactDetailsInput { ... and the following variables: ```json - { "userInput": { "name": "George", @@ -235,7 +256,9 @@ input ContactDetailsInput { } ``` -... and an unmarshal function that returns an error if the email is invalid. The mutation will return an error containing the full path: +... and an unmarshal function that returns an error if the email is invalid. +The mutation will return an error containing the full path: + ```json { "message": "email invalid", diff --git a/go.mod b/go.mod index 141c03e3a3..b4696bc15d 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/99designs/gqlgen go 1.18 require ( + github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.5.0 github.com/hashicorp/golang-lru/v2 v2.0.3 github.com/kevinmbeaulieu/eq-go v1.0.0 diff --git a/go.sum b/go.sum index 32203df77f..309b6f938c 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPDrgxJa9mE= diff --git a/graphql/uuid.go b/graphql/uuid.go new file mode 100644 index 0000000000..1bfb7680d5 --- /dev/null +++ b/graphql/uuid.go @@ -0,0 +1,26 @@ +package graphql + +import ( + "fmt" + "io" + "strconv" + + "github.com/google/uuid" +) + +func MarshalUUID(id uuid.UUID) Marshaler { + return WriterFunc(func(w io.Writer) { + _, _ = io.WriteString(w, strconv.Quote(id.String())) + }) +} + +func UnmarshalUUID(v any) (uuid.UUID, error) { + switch v := v.(type) { + case string: + return uuid.Parse(v) + case []byte: + return uuid.ParseBytes(v) + default: + return uuid.Nil, fmt.Errorf("%T is not a uuid", v) + } +} diff --git a/graphql/uuid_test.go b/graphql/uuid_test.go new file mode 100644 index 0000000000..3dd7d68ff8 --- /dev/null +++ b/graphql/uuid_test.go @@ -0,0 +1,56 @@ +package graphql + +import ( + "testing" + + "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +func TestMarshalUUID(t *testing.T) { + t.Run("Null Values", func(t *testing.T) { + assert.Equal(t, uuid.Nil, uuid.MustParse("00000000-0000-0000-0000-000000000000")) + }) + + t.Run("Valid Values", func(t *testing.T) { + + var values = []struct { + input uuid.UUID + expected string + }{ + {uuid.MustParse("fd5343a9-0372-11ee-9fb2-0242ac160014"), "\"fd5343a9-0372-11ee-9fb2-0242ac160014\""}, + } + for _, v := range values { + assert.Equal(t, v.expected, m2s(MarshalUUID(v.input))) + } + }) +} + +func TestUnmarshalUUID(t *testing.T) { + t.Run("Invalid Non-String Values", func(t *testing.T) { + var values = []interface{}{123, 1.2345678901, 1.2e+20, 1.2e-20, true, false, nil} + for _, v := range values { + result, err := UnmarshalUUID(v) + assert.Equal(t, uuid.Nil, result) + assert.ErrorContains(t, err, "is not a uuid") + } + }) + + t.Run("Invalid String Values", func(t *testing.T) { + var values = []struct { + input string + expected string + }{ + {"X50e8400-e29b-41d4-a716-446655440000", "invalid UUID format"}, + {"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "invalid UUID format"}, + {"F50e8400-e29b-41d4-a716-44665544000", "invalid UUID length: 35"}, + {"aaa", "invalid UUID length: 3"}, + {"", "invalid UUID length: 0"}, + } + for _, v := range values { + result, err := UnmarshalUUID(v.input) + assert.Equal(t, uuid.Nil, result) + assert.ErrorContains(t, err, v.expected) + } + }) +} From 6505f8be0d99593376d6c9a0dea00af5e3c018ea Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Fri, 8 Sep 2023 09:53:08 -0400 Subject: [PATCH 24/54] Update gqlparser (#2785) Signed-off-by: Steve Coffman --- _examples/go.mod | 2 +- _examples/go.sum | 16 +++------------- _examples/websocket-initfunc/server/go.mod | 2 +- _examples/websocket-initfunc/server/go.sum | 18 ++---------------- go.mod | 2 +- go.sum | 17 +++-------------- 6 files changed, 11 insertions(+), 46 deletions(-) diff --git a/_examples/go.mod b/_examples/go.mod index 7fff38167d..1a50ad9e08 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -13,7 +13,7 @@ require ( github.com/rs/cors v1.9.0 github.com/stretchr/testify v1.8.2 github.com/vektah/dataloaden v0.3.0 - github.com/vektah/gqlparser/v2 v2.5.8 + github.com/vektah/gqlparser/v2 v2.5.9 sourcegraph.com/sourcegraph/appdash v0.0.0-20211028080628-e2786a622600 ) diff --git a/_examples/go.sum b/_examples/go.sum index 4b69acaff2..09d2c205bb 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -1,7 +1,6 @@ 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/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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -23,11 +22,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyf github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -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 h1:R6zcoZZbvVcGMvDCKo45A9U/lzYyzl5NfYIvznmDfE4= github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -50,7 +44,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= 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/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= @@ -60,7 +53,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -68,8 +60,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/vektah/dataloaden v0.3.0 h1:ZfVN2QD6swgvp+tDqdH/OIT/wu3Dhu0cus0k5gIZS84= github.com/vektah/dataloaden v0.3.0/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= -github.com/vektah/gqlparser/v2 v2.5.8 h1:pm6WOnGdzFOCfcQo9L3+xzW51mKrlwTEg4Wr7AH1JW4= -github.com/vektah/gqlparser/v2 v2.5.8/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= +github.com/vektah/gqlparser/v2 v2.5.9 h1:bFju9t/E8shqIcDGayKdpl6OHBplFZEeYac9SALiRZE= +github.com/vektah/gqlparser/v2 v2.5.9/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -116,12 +108,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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.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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/websocket-initfunc/server/go.mod b/_examples/websocket-initfunc/server/go.mod index 6d71b73d17..4eb41a80fa 100644 --- a/_examples/websocket-initfunc/server/go.mod +++ b/_examples/websocket-initfunc/server/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-chi/chi v1.5.4 github.com/gorilla/websocket v1.5.0 github.com/rs/cors v1.9.0 - github.com/vektah/gqlparser/v2 v2.5.8 + github.com/vektah/gqlparser/v2 v2.5.9 ) require ( diff --git a/_examples/websocket-initfunc/server/go.sum b/_examples/websocket-initfunc/server/go.sum index 10fb21231c..0c9022c86f 100644 --- a/_examples/websocket-initfunc/server/go.sum +++ b/_examples/websocket-initfunc/server/go.sum @@ -3,12 +3,9 @@ github.com/99designs/gqlgen v0.17.34/go.mod h1:Axcd3jIFHBVcqzixujJQr1wGqE+lGTpz6 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/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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= @@ -17,25 +14,14 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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/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/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/vektah/gqlparser/v2 v2.5.8 h1:pm6WOnGdzFOCfcQo9L3+xzW51mKrlwTEg4Wr7AH1JW4= -github.com/vektah/gqlparser/v2 v2.5.8/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -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= +github.com/vektah/gqlparser/v2 v2.5.9 h1:bFju9t/E8shqIcDGayKdpl6OHBplFZEeYac9SALiRZE= +github.com/vektah/gqlparser/v2 v2.5.9/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/go.mod b/go.mod index b4696bc15d..9707104154 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.25.5 - github.com/vektah/gqlparser/v2 v2.5.8 + github.com/vektah/gqlparser/v2 v2.5.9 golang.org/x/text v0.9.0 golang.org/x/tools v0.9.3 google.golang.org/protobuf v1.30.0 diff --git a/go.sum b/go.sum index 309b6f938c..cf7d846d75 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,6 @@ 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/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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= @@ -22,11 +21,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.3 h1:kmRrRLlInXvng0SmLxmQpQkpbYAvcXm7NPD github.com/hashicorp/golang-lru/v2 v2.0.3/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/kevinmbeaulieu/eq-go v1.0.0 h1:AQgYHURDOmnVJ62jnEk0W/7yFKEn+Lv8RHN6t7mB0Zo= 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 h1:R6zcoZZbvVcGMvDCKo45A9U/lzYyzl5NfYIvznmDfE4= github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc= github.com/matryer/moq v0.2.7 h1:RtpiPUM8L7ZSCbSwK+QcZH/E9tgqAkFjKQxsRs25b4w= @@ -43,19 +37,17 @@ 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.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= 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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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/v2 v2.5.8 h1:pm6WOnGdzFOCfcQo9L3+xzW51mKrlwTEg4Wr7AH1JW4= -github.com/vektah/gqlparser/v2 v2.5.8/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME= +github.com/vektah/gqlparser/v2 v2.5.9 h1:bFju9t/E8shqIcDGayKdpl6OHBplFZEeYac9SALiRZE= +github.com/vektah/gqlparser/v2 v2.5.9/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= 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.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -99,12 +91,9 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 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.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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From ccae370e96cbca6ce5deaabf28a6d57e3b181b3b Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Fri, 8 Sep 2023 10:58:23 -0400 Subject: [PATCH 25/54] release v0.17.37 --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index 2568e9e7c4..8a6746a290 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 70bbc77601..f6c65eaa4b 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index cf5f7be192..f4d51a2421 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index ed79e492af..1ae290a4a7 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index 288ce39542..a19072fd35 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index 20a574af4c..71bf8d95d4 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index f37815799a..7431baca7e 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 6dbe081585..94cb013df2 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index dbc098ee93..b9e38a9495 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" diff --git a/graphql/version.go b/graphql/version.go index cc4e6c903b..a77bb53035 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.36-dev" +const Version = "v0.17.37" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index b71816a500..327bb8b506 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.36-dev +// Code generated by github.com/99designs/gqlgen version v0.17.37 import ( "context" From f90ac05e42fcc97addda2d32e3cc16565f55ed98 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Fri, 8 Sep 2023 10:59:01 -0400 Subject: [PATCH 26/54] v0.17.37 postrelease bump --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index 8a6746a290..2c852ff264 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index f6c65eaa4b..76de5ec59d 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index f4d51a2421..562300997a 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 1ae290a4a7..1dbbceda70 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index a19072fd35..40fb3ebf99 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index 71bf8d95d4..f33a76f483 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index 7431baca7e..b75cc893d6 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 94cb013df2..87f37dacf4 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index b9e38a9495..a4989797a0 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" diff --git a/graphql/version.go b/graphql/version.go index a77bb53035..bcbf814cec 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.37" +const Version = "v0.17.37-dev" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index 327bb8b506..f19626268c 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.37 +// Code generated by github.com/99designs/gqlgen version v0.17.37-dev import ( "context" From 9930e5740e0670a69bfd4397d87222b49cf7f0e6 Mon Sep 17 00:00:00 2001 From: "Roman A. Grigorovich" Date: Sat, 9 Sep 2023 03:07:23 +0300 Subject: [PATCH 27/54] Ability to use forceGenerate and extraFields together (#2788) * Ability to user forceGenerate and extraFields together * Some docs for forceGenerate added --------- Co-authored-by: Roman A. Grigorovich --- codegen/config/config.go | 11 +++++------ docs/content/config.md | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/codegen/config/config.go b/codegen/config/config.go index ddf10ac21d..1e844f4696 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -600,12 +600,7 @@ func (c *Config) autobind() error { ps := c.Packages.LoadAll(c.AutoBind...) for _, t := range c.Schema.Types { - if c.Models.UserDefined(t.Name) { - continue - } - - if c.Models[t.Name].ForceGenerate { - delete(c.Models, t.Name) + if c.Models.UserDefined(t.Name) || c.Models[t.Name].ForceGenerate { continue } @@ -621,6 +616,10 @@ func (c *Config) autobind() error { } for i, t := range c.Models { + if t.ForceGenerate { + continue + } + for j, m := range t.Model { pkg, typename := code.PkgAndType(m) diff --git a/docs/content/config.md b/docs/content/config.md index 26dba6fed8..f464359aca 100644 --- a/docs/content/config.md +++ b/docs/content/config.md @@ -165,6 +165,12 @@ type User @goModel(model: "github.com/my/app/models.User") { @goTag(key: "xorm", value: "-") @goTag(key: "yaml") } + +# This make sense when autobind activated. +type Person @goModel(forceGenerate: true) { + id: ID! + name: String! +} ``` The builtin directives `goField`, `goModel` and `goTag` are automatically registered to `skip_runtime`. Any directives registered as `skip_runtime` will not exposed during introspection and are used during code generation only. From f01d580501ddca4cf20b6fbf7f937be8509466bf Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Fri, 8 Sep 2023 20:07:53 -0400 Subject: [PATCH 28/54] Add new changelog (#2787) Signed-off-by: Steve Coffman --- CHANGELOG.md | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 662377f1b8..d977ea4063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,178 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased](https://github.com/99designs/gqlgen/compare/v0.17.35...HEAD) +## [Unreleased](https://github.com/99designs/gqlgen/compare/v0.17.37...HEAD) + +## [v0.17.37](https://github.com/99designs/gqlgen/compare/v0.17.36...v0.17.37) - 2023-09-08 +- ccae370e release v0.17.37 + +- 6505f8be Update gqlparser (#2785) + +
153ec470 add uuid type (#2751) (closes #2749) + +* add uuid type + +* add uuid example + +* add uuid scalar doc + +* strconv.Quote + +* Apply suggestions from code review + +* fix + + + +--------- + +
+ +
fa471180 ForceGenerate parameter to [@goModel](https://github.com/goModel) added. (#2780) + +* forceGenerate to docs added + +--------- + +
+ +
11bb9b18 codegen: add support for `go_build_tags` option in gqlgen.yaml (#2784) + +* codegen: support go_build_tags option in gqlgen.yaml + +* chore: added test + +* docs/content: update config example + +* chore: more comment + +
+ +
bee47dcf fix flaky test TestSubscriptions (#2779) + +* fix flaky test TestSubscriptions + +* update other copy of the test + +
+ +- a41f4daa docs: short-lived loader (#2778) + +- cc4e0ba2 ensure HasOperationContext checks for nil (#2776) + +
a1ca2204 fix typo in TESTING.md server path (#2774) + +following TESTING.md instructions, I got an error: +"stat ./server/server.go: no such file or directory" + +server.go path is: integration/server/cmd/integration/server.go + +
+ +
1cde8c3f return internal types in schema introspection (#2773) + +according to graphql spec: +``` +types: return the set of all named types contained within this schema. +Any named type which can be found through a field of any introspection type must be included in this set. +``` +source: https://github.com/graphql/graphql-spec/blob/main/spec/Section%204%20--%20Introspection.md#the-__schema-type + +some clients libs (like HotChocolate for C#) depends on this behavior. + +
+ +- 065aea3e Fix gqlgen truncates tag value with colon (#2759) + +- d6270e4f Update subsciptions documentation to correctly close channel (#2753) + +- 2d8673a6 Add Model references to Interface (#2738) + +- 790d7a75 Allow GraphiQL headers to be set when creating the playground handler (#2740) (closes #2739) + +- 0eb95dc4 v0.17.36 postrelease bump + + + + + + +## [v0.17.36](https://github.com/99designs/gqlgen/compare/v0.17.35...v0.17.36) - 2023-07-27 +- bd6cfd31 release v0.17.36 + +
60ec0d86 Fix plugin template resolution (#2733) (closes #2262) + +- According to the documentation comment for [templates.Options], if the + `Template` and `TemplateFS` fields are empty, it `Render` should find + the `.gotpl` files from the calling plugin. However, it looks like + helper function. This results in broken behavior in consumers such as + [infiotinc/gqlgenc](https://github.com/infiotinc/gqlgenc) when they + use the latest version of `gqlgen` as instead of finding the template + from the plugin, the test template from this package is used which + outputs only: `this is my test package`. +- The cause for this is that `runtime.Caller` was still only skipping + one stack level which means that it was finding the `Render` function + instead of its caller. + +
+ +- 76d444c1 Make models configurable via template (#2730) + +- abe3ffde Don't set the package variable for the new Resolver Template (#2725) + +
febf9566 Make the resolver implementation configurable via a new template resolver.gotpl (#2720) + +* Make an optional resolver.gotpl ResolverTemplate to implement a custom resolver + +* Add test + +* Add documetation for the new resolver option + +* Change the tab to spaces + +* remove unecessary test assertion :/ + +
+ +
bda30260 Fixed Data Loader docs (#2723) + +Also updated to v7 + +
+ +
16c9eb64 Fix docs (#2722) + +* docs: fix variable names in dataloader sample + +* fix: request-scoped middleware + +
+ +
b233a01b docs: update dataloader docs (#2719) + +* docs: update example + +* docs: update example + +* fix: import + +
+ +- cccc7389 Added go mod tidy to quick start guide (#2718) (closes #2717, #2651, #2641, #2614, #2576) + +- 9adc7b81 Update gqlparser to v2.5.8 (#2716) + +- b442fbf4 Post v0.17.35 changelog update + +- 57c12199 v0.17.35 postrelease bump + + + + + ## [v0.17.35](https://github.com/99designs/gqlgen/compare/v0.17.34...v0.17.35) - 2023-07-15 - 05006bf1 release v0.17.35 From fceb33111bef2bbbf14468d78888098ac8968351 Mon Sep 17 00:00:00 2001 From: Steven Schobert Date: Mon, 11 Sep 2023 12:46:52 -0500 Subject: [PATCH 29/54] Fix rand int docs link in Getting Started (#2789) --- docs/content/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index 42fee8eb9a..985c16e031 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -135,7 +135,7 @@ type Resolver struct{ } ``` -Returning to `graph/schema.resolvers.go`, let's implement the bodies of those automatically generated resolver functions. For `CreateTodo`, we'll use the [`math.rand` package](https://pkg.go.dev/math/rand#Rand.Int) to simply return a todo with a randomly generated ID and store that in the in-memory todos list --- in a real app, you're likely to use a database or some other backend service. +Returning to `graph/schema.resolvers.go`, let's implement the bodies of those automatically generated resolver functions. For `CreateTodo`, we'll use the [`crypto.rand` package](https://pkg.go.dev/crypto/rand#Int) to simply return a todo with a randomly generated ID and store that in the in-memory todos list --- in a real app, you're likely to use a database or some other backend service. ```go func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { From 625ca2e58aba47cd540f0fb47e048a743a896906 Mon Sep 17 00:00:00 2001 From: Marcus Thelin Date: Thu, 14 Sep 2023 20:45:24 +0200 Subject: [PATCH 30/54] Make it possible to pass UI headers (#2793) --- graphql/playground/playground.go | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/graphql/playground/playground.go b/graphql/playground/playground.go index f3ebabf3d3..1719cd7388 100644 --- a/graphql/playground/playground.go +++ b/graphql/playground/playground.go @@ -58,18 +58,24 @@ var page = template.Must(template.New("graphiql").Parse(` const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:'; const subscriptionUrl = wsProto + '//' + location.host + {{.endpoint}}; {{- end}} -{{- if .headers}} - const headers = {{.headers}}; +{{- if .fetcherHeaders}} + const fetcherHeaders = {{.fetcherHeaders}}; {{- else}} - const headers = undefined; + const fetcherHeaders = undefined; +{{- end}} +{{- if .uiHeaders}} + const uiHeaders = {{.uiHeaders}}; +{{- else}} + const uiHeaders = undefined; {{- end}} - const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl, headers }); + const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl, headers: fetcherHeaders }); ReactDOM.render( React.createElement(GraphiQL, { fetcher: fetcher, isHeadersEditorEnabled: true, - shouldPersistHeaders: true + shouldPersistHeaders: true, + headers: JSON.stringify(uiHeaders, null, 2) }), document.getElementById('graphiql'), ); @@ -80,16 +86,20 @@ var page = template.Must(template.New("graphiql").Parse(` // Handler responsible for setting up the playground func Handler(title string, endpoint string) http.HandlerFunc { - return HandlerWithHeaders(title, endpoint, nil) + return HandlerWithHeaders(title, endpoint, nil, nil) } -func HandlerWithHeaders(title string, endpoint string, headers map[string]string) http.HandlerFunc { +// HandlerWithHeaders sets up the playground. +// fetcherHeaders are used by the playground's fetcher instance and will not be visible in the UI. +// uiHeaders are default headers that will show up in the UI headers editor. +func HandlerWithHeaders(title string, endpoint string, fetcherHeaders map[string]string, uiHeaders map[string]string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "text/html; charset=UTF-8") err := page.Execute(w, map[string]interface{}{ "title": title, "endpoint": endpoint, - "headers": headers, + "fetcherHeaders": fetcherHeaders, + "uiHeaders": uiHeaders, "endpointIsAbsolute": endpointHasScheme(endpoint), "subscriptionEndpoint": getSubscriptionEndpoint(endpoint), "version": "3.0.1", From c89860bdd01827ad0f7a3f2020935e2ae115ecb7 Mon Sep 17 00:00:00 2001 From: M Date: Fri, 15 Sep 2023 19:48:26 +0700 Subject: [PATCH 31/54] refactor: return `null` instead of zero value uuid (#2794) --- graphql/uuid.go | 9 ++++----- graphql/uuid_test.go | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/graphql/uuid.go b/graphql/uuid.go index 1bfb7680d5..e9f22dccdb 100644 --- a/graphql/uuid.go +++ b/graphql/uuid.go @@ -2,16 +2,15 @@ package graphql import ( "fmt" - "io" - "strconv" "github.com/google/uuid" ) func MarshalUUID(id uuid.UUID) Marshaler { - return WriterFunc(func(w io.Writer) { - _, _ = io.WriteString(w, strconv.Quote(id.String())) - }) + if id == uuid.Nil { + return Null + } + return MarshalString(id.String()) } func UnmarshalUUID(v any) (uuid.UUID, error) { diff --git a/graphql/uuid_test.go b/graphql/uuid_test.go index 3dd7d68ff8..1d20996449 100644 --- a/graphql/uuid_test.go +++ b/graphql/uuid_test.go @@ -9,7 +9,7 @@ import ( func TestMarshalUUID(t *testing.T) { t.Run("Null Values", func(t *testing.T) { - assert.Equal(t, uuid.Nil, uuid.MustParse("00000000-0000-0000-0000-000000000000")) + assert.Equal(t, "null", m2s(MarshalUUID(uuid.Nil))) }) t.Run("Valid Values", func(t *testing.T) { From 5f452ce2dbfc4171fc021c10de11b435a60c8955 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Tue, 19 Sep 2023 08:26:31 -0400 Subject: [PATCH 32/54] Update gqlparser to 2.5.10 (#2798) Signed-off-by: Steve Coffman --- _examples/go.mod | 2 +- _examples/go.sum | 4 ++-- _examples/websocket-initfunc/server/go.mod | 2 +- _examples/websocket-initfunc/server/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/_examples/go.mod b/_examples/go.mod index 1a50ad9e08..bd3fcb10bc 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -13,7 +13,7 @@ require ( github.com/rs/cors v1.9.0 github.com/stretchr/testify v1.8.2 github.com/vektah/dataloaden v0.3.0 - github.com/vektah/gqlparser/v2 v2.5.9 + github.com/vektah/gqlparser/v2 v2.5.10 sourcegraph.com/sourcegraph/appdash v0.0.0-20211028080628-e2786a622600 ) diff --git a/_examples/go.sum b/_examples/go.sum index 09d2c205bb..0efcf708e3 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -60,8 +60,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/vektah/dataloaden v0.3.0 h1:ZfVN2QD6swgvp+tDqdH/OIT/wu3Dhu0cus0k5gIZS84= github.com/vektah/dataloaden v0.3.0/go.mod h1:/HUdMve7rvxZma+2ZELQeNh88+003LL7Pf/CZ089j8U= -github.com/vektah/gqlparser/v2 v2.5.9 h1:bFju9t/E8shqIcDGayKdpl6OHBplFZEeYac9SALiRZE= -github.com/vektah/gqlparser/v2 v2.5.9/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= +github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= +github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/_examples/websocket-initfunc/server/go.mod b/_examples/websocket-initfunc/server/go.mod index 4eb41a80fa..20722874ba 100644 --- a/_examples/websocket-initfunc/server/go.mod +++ b/_examples/websocket-initfunc/server/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-chi/chi v1.5.4 github.com/gorilla/websocket v1.5.0 github.com/rs/cors v1.9.0 - github.com/vektah/gqlparser/v2 v2.5.9 + github.com/vektah/gqlparser/v2 v2.5.10 ) require ( diff --git a/_examples/websocket-initfunc/server/go.sum b/_examples/websocket-initfunc/server/go.sum index 0c9022c86f..352a0a6587 100644 --- a/_examples/websocket-initfunc/server/go.sum +++ b/_examples/websocket-initfunc/server/go.sum @@ -21,7 +21,7 @@ github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/vektah/gqlparser/v2 v2.5.9 h1:bFju9t/E8shqIcDGayKdpl6OHBplFZEeYac9SALiRZE= -github.com/vektah/gqlparser/v2 v2.5.9/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= +github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= +github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/go.mod b/go.mod index 9707104154..f856dac1cf 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.25.5 - github.com/vektah/gqlparser/v2 v2.5.9 + github.com/vektah/gqlparser/v2 v2.5.10 golang.org/x/text v0.9.0 golang.org/x/tools v0.9.3 google.golang.org/protobuf v1.30.0 diff --git a/go.sum b/go.sum index cf7d846d75..85c8dff9fd 100644 --- a/go.sum +++ b/go.sum @@ -46,8 +46,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ 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/v2 v2.5.9 h1:bFju9t/E8shqIcDGayKdpl6OHBplFZEeYac9SALiRZE= -github.com/vektah/gqlparser/v2 v2.5.9/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= +github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= +github.com/vektah/gqlparser/v2 v2.5.10/go.mod h1:1rCcfwB2ekJofmluGWXMSEnPMZgbxzwj6FaZ/4OT8Cc= 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.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= From d9077fac9c2320b28744fb43ab1d00c4d50f0af8 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Tue, 19 Sep 2023 08:28:14 -0400 Subject: [PATCH 33/54] release v0.17.38 --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index 2c852ff264..fd9be3a4d4 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 76de5ec59d..b8fdd63ad0 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index 562300997a..fdcab836bf 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 1dbbceda70..8d59f80f5b 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index 40fb3ebf99..aadcb04838 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index f33a76f483..3c954e89af 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index b75cc893d6..bd8f4920c3 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 87f37dacf4..c76b6d8545 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index a4989797a0..762048ad2f 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" diff --git a/graphql/version.go b/graphql/version.go index bcbf814cec..a1666bc727 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.37-dev" +const Version = "v0.17.38" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index f19626268c..9943ab0ce6 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.37-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38 import ( "context" From f3b860336bfcc7307713420e703ee5badec029a4 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Tue, 19 Sep 2023 08:28:52 -0400 Subject: [PATCH 34/54] v0.17.38 postrelease bump --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index fd9be3a4d4..d718cd32af 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index b8fdd63ad0..8a16e4e038 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index fdcab836bf..c1fffebd8a 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 8d59f80f5b..b33d5dbbc7 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index aadcb04838..43767d481b 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index 3c954e89af..b2aba8e612 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index bd8f4920c3..6c5f12be78 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index c76b6d8545..ff97881b3e 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index 762048ad2f..a5c7fff00b 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/graphql/version.go b/graphql/version.go index a1666bc727..8a5f5646b8 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.38" +const Version = "v0.17.38-dev" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index 9943ab0ce6..c284018666 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.38 +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" From af4d3943308b7a84464771e5ed6b578ba40ee0c3 Mon Sep 17 00:00:00 2001 From: Chris Pride Date: Tue, 19 Sep 2023 13:23:19 -0700 Subject: [PATCH 35/54] Allow WebsocketInitFunc to add payload to Ack (#4) (#2791) * Allow WebsocketInitFunc to add payload to Ack The connection ACK message in the protocol for both graphql-ws and graphql-transport-ws allows for a payload in the connection ack message. We really wanted to use this to establish better telemetry in our use of websockets in graphql. * Fix lint error in test * Switch argument ordering. --------- Co-authored-by: Chris Pride --- _examples/websocket-initfunc/server/server.go | 8 +-- graphql/handler/transport/websocket.go | 16 +++++- graphql/handler/transport/websocket_test.go | 57 ++++++++++++++----- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/_examples/websocket-initfunc/server/server.go b/_examples/websocket-initfunc/server/server.go index 4704708dab..64c3010f81 100644 --- a/_examples/websocket-initfunc/server/server.go +++ b/_examples/websocket-initfunc/server/server.go @@ -18,12 +18,12 @@ import ( "github.com/rs/cors" ) -func webSocketInit(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { +func webSocketInit(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) { // Get the token from payload payload := initPayload["authToken"] token, ok := payload.(string) if !ok || token == "" { - return nil, errors.New("authToken not found in transport payload") + return nil, nil, errors.New("authToken not found in transport payload") } // Perform token verification and authentication... @@ -32,7 +32,7 @@ func webSocketInit(ctx context.Context, initPayload transport.InitPayload) (cont // put it in context ctxNew := context.WithValue(ctx, "username", userId) - return ctxNew, nil + return ctxNew, nil, nil } const defaultPort = "8080" @@ -62,7 +62,7 @@ func main() { return true }, }, - InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (*transport.InitPayload, context.Context, error) { return webSocketInit(ctx, initPayload) }, }) diff --git a/graphql/handler/transport/websocket.go b/graphql/handler/transport/websocket.go index acd124fe8e..ed1d9588c9 100644 --- a/graphql/handler/transport/websocket.go +++ b/graphql/handler/transport/websocket.go @@ -44,7 +44,7 @@ type ( initPayload InitPayload } - WebsocketInitFunc func(ctx context.Context, initPayload InitPayload) (context.Context, error) + WebsocketInitFunc func(ctx context.Context, initPayload InitPayload) (context.Context, *InitPayload, error) WebsocketErrorFunc func(ctx context.Context, err error) // Callback called when websocket is closed. @@ -179,8 +179,10 @@ func (c *wsConnection) init() bool { } } + var initAckPayload *InitPayload = nil if c.InitFunc != nil { - ctx, err := c.InitFunc(c.ctx, c.initPayload) + var ctx context.Context + ctx, initAckPayload, err = c.InitFunc(c.ctx, c.initPayload) if err != nil { c.sendConnectionError(err.Error()) c.close(websocket.CloseNormalClosure, "terminated") @@ -189,7 +191,15 @@ func (c *wsConnection) init() bool { c.ctx = ctx } - c.write(&message{t: connectionAckMessageType}) + if initAckPayload != nil { + initJsonAckPayload, err := json.Marshal(*initAckPayload) + if err != nil { + panic(err) + } + c.write(&message{t: connectionAckMessageType, payload: initJsonAckPayload}) + } else { + c.write(&message{t: connectionAckMessageType}) + } c.write(&message{t: keepAliveMessageType}) case connectionCloseMessageType: c.close(websocket.CloseNormalClosure, "terminated") diff --git a/graphql/handler/transport/websocket_test.go b/graphql/handler/transport/websocket_test.go index 9ac8ad65cc..678bfeab25 100644 --- a/graphql/handler/transport/websocket_test.go +++ b/graphql/handler/transport/websocket_test.go @@ -207,8 +207,8 @@ func TestWebsocketInitFunc(t *testing.T) { t.Run("accept connection if WebsocketInitFunc is provided and is accepting connection", func(t *testing.T) { h := testserver.New() h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { - return context.WithValue(ctx, ckey("newkey"), "newvalue"), nil + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) { + return context.WithValue(ctx, ckey("newkey"), "newvalue"), nil, nil }, }) srv := httptest.NewServer(h) @@ -226,8 +226,8 @@ func TestWebsocketInitFunc(t *testing.T) { t.Run("reject connection if WebsocketInitFunc is provided and is accepting connection", func(t *testing.T) { h := testserver.New() h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { - return ctx, errors.New("invalid init payload") + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) { + return ctx, nil, errors.New("invalid init payload") }, }) srv := httptest.NewServer(h) @@ -261,8 +261,8 @@ func TestWebsocketInitFunc(t *testing.T) { h := handler.New(es) h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) { - return context.WithValue(ctx, ckey("newkey"), "newvalue"), nil + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) { + return context.WithValue(ctx, ckey("newkey"), "newvalue"), nil, nil }, }) @@ -282,7 +282,7 @@ func TestWebsocketInitFunc(t *testing.T) { h := testserver.New() var cancel func() h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, _ transport.InitPayload) (newCtx context.Context, _ error) { + InitFunc: func(ctx context.Context, _ transport.InitPayload) (newCtx context.Context, _ *transport.InitPayload, _ error) { newCtx, cancel = context.WithTimeout(transport.AppendCloseReason(ctx, "beep boop"), time.Millisecond*5) return }, @@ -303,6 +303,33 @@ func TestWebsocketInitFunc(t *testing.T) { assert.Equal(t, m.Type, connectionErrorMsg) assert.Equal(t, string(m.Payload), `{"message":"beep boop"}`) }) + t.Run("accept connection if WebsocketInitFunc is provided and is accepting connection", func(t *testing.T) { + h := testserver.New() + h.AddTransport(transport.Websocket{ + InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) { + initResponsePayload := transport.InitPayload{"trackingId": "123-456"} + return context.WithValue(ctx, ckey("newkey"), "newvalue"), &initResponsePayload, nil + }, + }) + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnect(srv.URL) + defer c.Close() + + require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) + + connAck := readOp(c) + assert.Equal(t, connectionAckMsg, connAck.Type) + + var payload map[string]interface{} + err := json.Unmarshal(connAck.Payload, &payload) + if err != nil { + t.Fatal("Unexpected Error", err) + } + assert.EqualValues(t, "123-456", payload["trackingId"]) + assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) + }) } func TestWebSocketInitTimeout(t *testing.T) { @@ -382,8 +409,8 @@ func TestWebSocketErrorFunc(t *testing.T) { t.Run("init func errors do not call the error handler", func(t *testing.T) { h := testserver.New() h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, _ transport.InitPayload) (context.Context, error) { - return ctx, errors.New("this is not what we agreed upon") + InitFunc: func(ctx context.Context, _ transport.InitPayload) (context.Context, *transport.InitPayload, error) { + return ctx, nil, errors.New("this is not what we agreed upon") }, ErrorFunc: func(_ context.Context, err error) { assert.Fail(t, "the error handler got called when it shouldn't have", "error: "+err.Error()) @@ -400,10 +427,10 @@ func TestWebSocketErrorFunc(t *testing.T) { t.Run("init func context closes do not call the error handler", func(t *testing.T) { h := testserver.New() h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, _ transport.InitPayload) (context.Context, error) { + InitFunc: func(ctx context.Context, _ transport.InitPayload) (context.Context, *transport.InitPayload, error) { newCtx, cancel := context.WithCancel(ctx) time.AfterFunc(time.Millisecond*5, cancel) - return newCtx, nil + return newCtx, nil, nil }, ErrorFunc: func(_ context.Context, err error) { assert.Fail(t, "the error handler got called when it shouldn't have", "error: "+err.Error()) @@ -423,9 +450,9 @@ func TestWebSocketErrorFunc(t *testing.T) { h := testserver.New() var cancel func() h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, _ transport.InitPayload) (newCtx context.Context, _ error) { + InitFunc: func(ctx context.Context, _ transport.InitPayload) (newCtx context.Context, _ *transport.InitPayload, _ error) { newCtx, cancel = context.WithDeadline(ctx, time.Now().Add(time.Millisecond*5)) - return newCtx, nil + return newCtx, nil, nil }, ErrorFunc: func(_ context.Context, err error) { assert.Fail(t, "the error handler got called when it shouldn't have", "error: "+err.Error()) @@ -477,8 +504,8 @@ func TestWebSocketCloseFunc(t *testing.T) { h := testserver.New() closeFuncCalled := make(chan bool, 1) h.AddTransport(transport.Websocket{ - InitFunc: func(ctx context.Context, _ transport.InitPayload) (context.Context, error) { - return ctx, errors.New("error during init") + InitFunc: func(ctx context.Context, _ transport.InitPayload) (context.Context, *transport.InitPayload, error) { + return ctx, nil, errors.New("error during init") }, CloseFunc: func(_ context.Context, _closeCode int) { closeFuncCalled <- true From 3e2393f3afe1f3f530c34f4dbbece47bde6e736b Mon Sep 17 00:00:00 2001 From: Vlad Tokarev Date: Fri, 22 Sep 2023 23:23:14 +0300 Subject: [PATCH 36/54] add close flag into wsConnection to avoid duplicate calls of CloseFunc (#2803) * add close flag into wsConnection to avoid duplicate calls of CloseFunc * add test * Fix linter error --- graphql/handler/transport/websocket.go | 6 ++++ graphql/handler/transport/websocket_test.go | 33 +++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/graphql/handler/transport/websocket.go b/graphql/handler/transport/websocket.go index ed1d9588c9..8b375465c0 100644 --- a/graphql/handler/transport/websocket.go +++ b/graphql/handler/transport/websocket.go @@ -40,6 +40,7 @@ type ( keepAliveTicker *time.Ticker pingPongTicker *time.Ticker exec graphql.GraphExecutor + closed bool initPayload InitPayload } @@ -441,10 +442,15 @@ func (c *wsConnection) sendConnectionError(format string, args ...interface{}) { func (c *wsConnection) close(closeCode int, message string) { c.mu.Lock() + if c.closed { + c.mu.Unlock() + return + } _ = c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(closeCode, message)) for _, closer := range c.active { closer() } + c.closed = true c.mu.Unlock() _ = c.conn.Close() diff --git a/graphql/handler/transport/websocket_test.go b/graphql/handler/transport/websocket_test.go index 678bfeab25..d7c0a4c743 100644 --- a/graphql/handler/transport/websocket_test.go +++ b/graphql/handler/transport/websocket_test.go @@ -500,6 +500,39 @@ func TestWebSocketCloseFunc(t *testing.T) { } }) + t.Run("the on close handler gets called only once when the websocket is closed", func(t *testing.T) { + closeFuncCalled := make(chan bool, 1) + h := testserver.New() + h.AddTransport(transport.Websocket{ + CloseFunc: func(_ context.Context, _closeCode int) { + closeFuncCalled <- true + }, + }) + + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnect(srv.URL) + require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionInitMsg})) + assert.Equal(t, connectionAckMsg, readOp(c).Type) + assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) + require.NoError(t, c.WriteJSON(&operationMessage{Type: connectionTerminateMsg})) + + select { + case res := <-closeFuncCalled: + assert.True(t, res) + case <-time.NewTimer(time.Millisecond * 20).C: + assert.Fail(t, "The close handler was not called in time") + } + + select { + case <-closeFuncCalled: + assert.Fail(t, "The close handler was called more than once") + case <-time.NewTimer(time.Millisecond * 20).C: + // ok + } + }) + t.Run("init func errors call the close handler", func(t *testing.T) { h := testserver.New() closeFuncCalled := make(chan bool, 1) From 2c9f9c5f828bdda8aa03c4be7adf1d0c9abaa8f6 Mon Sep 17 00:00:00 2001 From: Parker Roan <50146661+parkerroan@users.noreply.github.com> Date: Mon, 25 Sep 2023 07:26:17 -0500 Subject: [PATCH 37/54] fix: CodeGen for omit_slice_element_pointers and GetMany Entity Resolvers (#2802) * remove ! from reps definition * adding tests * fixing tests * adding documentation * addressing lint * commit after go gonerate * gofmt Signed-off-by: Steve Coffman --------- Signed-off-by: Steve Coffman Co-authored-by: Steve Coffman --- plugin/federation/federation.go | 2 +- plugin/federation/federation_test.go | 44 ++++++++ plugin/federation/readme.md | 3 + .../testdata/entityresolver/generated/exec.go | 105 ++++++++++-------- .../federation/testdata/multi/multi.graphqls | 10 ++ plugin/federation/testdata/multi/multi.yml | 8 ++ 6 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 plugin/federation/testdata/multi/multi.graphqls create mode 100644 plugin/federation/testdata/multi/multi.yml diff --git a/plugin/federation/federation.go b/plugin/federation/federation.go index d0ee8435e1..9df9b8a23f 100644 --- a/plugin/federation/federation.go +++ b/plugin/federation/federation.go @@ -173,7 +173,7 @@ func (f *federation) InjectSourceLate(schema *ast.Schema) *ast.Source { entityResolverInputDefinitions += fmt.Sprintf("\t%s: %s\n", keyField.Field.ToGo(), keyField.Definition.Type.String()) } entityResolverInputDefinitions += "}" - resolvers += fmt.Sprintf("\t%s(reps: [%s!]!): [%s]\n", r.ResolverName, r.InputTypeName, e.Name) + resolvers += fmt.Sprintf("\t%s(reps: [%s]!): [%s]\n", r.ResolverName, r.InputTypeName, e.Name) } else { resolverArgs := "" for _, keyField := range r.KeyFields { diff --git a/plugin/federation/federation_test.go b/plugin/federation/federation_test.go index 7e8d924290..cc5b20ee3b 100644 --- a/plugin/federation/federation_test.go +++ b/plugin/federation/federation_test.go @@ -144,6 +144,50 @@ func TestCodeGenerationFederation2(t *testing.T) { require.NoError(t, f.GenerateCode(data)) } +// This test is to ensure that the input arguments are not +// changed when cfg.OmitSliceElementPointers is false OR true +func TestMultiWithOmitSliceElemPointersCfg(t *testing.T) { + + staticRepsString := "reps: [HelloByNamesInput]!" + t.Run("OmitSliceElementPointers true", func(t *testing.T) { + f, cfg := load(t, "testdata/multi/multi.yml") + cfg.OmitSliceElementPointers = true + err := f.MutateConfig(cfg) + require.NoError(t, err) + require.Len(t, cfg.Schema.Types["_Entity"].Types, 1) + require.Len(t, f.Entities, 1) + + entityGraphqlGenerated := false + for _, source := range cfg.Sources { + if source.Name != "federation/entity.graphql" { + continue + } + entityGraphqlGenerated = true + require.Contains(t, source.Input, staticRepsString) + } + require.True(t, entityGraphqlGenerated) + }) + + t.Run("OmitSliceElementPointers false", func(t *testing.T) { + f, cfg := load(t, "testdata/multi/multi.yml") + cfg.OmitSliceElementPointers = false + err := f.MutateConfig(cfg) + require.NoError(t, err) + require.Len(t, cfg.Schema.Types["_Entity"].Types, 1) + require.Len(t, f.Entities, 1) + + entityGraphqlGenerated := false + for _, source := range cfg.Sources { + if source.Name != "federation/entity.graphql" { + continue + } + entityGraphqlGenerated = true + require.Contains(t, source.Input, staticRepsString) + } + require.True(t, entityGraphqlGenerated) + }) +} + func TestInjectSourceLate(t *testing.T) { _, cfg := load(t, "testdata/allthethings/gqlgen.yml") entityGraphqlGenerated := false diff --git a/plugin/federation/readme.md b/plugin/federation/readme.md index 4333ed4797..d5dd0628a3 100644 --- a/plugin/federation/readme.md +++ b/plugin/federation/readme.md @@ -37,3 +37,6 @@ func (r *entityResolver) FindManyMultiHellosByName(ctx context.Context, reps []* /// } ``` + +**Note:** +If you are using `omit_slice_element_pointers: true` option in your config yaml, your `GetMany` resolver will still generate in the example above the same signature `FindManyMultiHellosByName(ctx context.Context, reps []*generated.ManyMultiHellosByNameInput) ([]*generated.MultiHello, error)`. But all other instances will continue to honor `omit_slice_element_pointers: true` \ No newline at end of file diff --git a/plugin/federation/testdata/entityresolver/generated/exec.go b/plugin/federation/testdata/entityresolver/generated/exec.go index 0b1e4a60ab..20ed74ad93 100644 --- a/plugin/federation/testdata/entityresolver/generated/exec.go +++ b/plugin/federation/testdata/entityresolver/generated/exec.go @@ -837,11 +837,11 @@ type Entity { findHelloByName(name: String!,): Hello! findHelloMultiSingleKeysByKey1AndKey2(key1: String!,key2: String!,): HelloMultiSingleKeys! findHelloWithErrorsByName(name: String!,): HelloWithErrors! - findManyMultiHelloByNames(reps: [MultiHelloByNamesInput!]!): [MultiHello] - findManyMultiHelloMultipleRequiresByNames(reps: [MultiHelloMultipleRequiresByNamesInput!]!): [MultiHelloMultipleRequires] - findManyMultiHelloRequiresByNames(reps: [MultiHelloRequiresByNamesInput!]!): [MultiHelloRequires] - findManyMultiHelloWithErrorByNames(reps: [MultiHelloWithErrorByNamesInput!]!): [MultiHelloWithError] - findManyMultiPlanetRequiresNestedByNames(reps: [MultiPlanetRequiresNestedByNamesInput!]!): [MultiPlanetRequiresNested] + findManyMultiHelloByNames(reps: [MultiHelloByNamesInput]!): [MultiHello] + findManyMultiHelloMultipleRequiresByNames(reps: [MultiHelloMultipleRequiresByNamesInput]!): [MultiHelloMultipleRequires] + findManyMultiHelloRequiresByNames(reps: [MultiHelloRequiresByNamesInput]!): [MultiHelloRequires] + findManyMultiHelloWithErrorByNames(reps: [MultiHelloWithErrorByNamesInput]!): [MultiHelloWithError] + findManyMultiPlanetRequiresNestedByNames(reps: [MultiPlanetRequiresNestedByNamesInput]!): [MultiPlanetRequiresNested] findPlanetMultipleRequiresByName(name: String!,): PlanetMultipleRequires! findPlanetRequiresByName(name: String!,): PlanetRequires! findPlanetRequiresNestedByName(name: String!,): PlanetRequiresNested! @@ -943,7 +943,7 @@ func (ec *executionContext) field_Entity_findManyMultiHelloByNames_args(ctx cont var arg0 []*model.MultiHelloByNamesInput if tmp, ok := rawArgs["reps"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reps")) - arg0, err = ec.unmarshalNMultiHelloByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInputᚄ(ctx, tmp) + arg0, err = ec.unmarshalNMultiHelloByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInput(ctx, tmp) if err != nil { return nil, err } @@ -958,7 +958,7 @@ func (ec *executionContext) field_Entity_findManyMultiHelloMultipleRequiresByNam var arg0 []*model.MultiHelloMultipleRequiresByNamesInput if tmp, ok := rawArgs["reps"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reps")) - arg0, err = ec.unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInputᚄ(ctx, tmp) + arg0, err = ec.unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInput(ctx, tmp) if err != nil { return nil, err } @@ -973,7 +973,7 @@ func (ec *executionContext) field_Entity_findManyMultiHelloRequiresByNames_args( var arg0 []*model.MultiHelloRequiresByNamesInput if tmp, ok := rawArgs["reps"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reps")) - arg0, err = ec.unmarshalNMultiHelloRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInputᚄ(ctx, tmp) + arg0, err = ec.unmarshalNMultiHelloRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInput(ctx, tmp) if err != nil { return nil, err } @@ -988,7 +988,7 @@ func (ec *executionContext) field_Entity_findManyMultiHelloWithErrorByNames_args var arg0 []*model.MultiHelloWithErrorByNamesInput if tmp, ok := rawArgs["reps"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reps")) - arg0, err = ec.unmarshalNMultiHelloWithErrorByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInputᚄ(ctx, tmp) + arg0, err = ec.unmarshalNMultiHelloWithErrorByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInput(ctx, tmp) if err != nil { return nil, err } @@ -1003,7 +1003,7 @@ func (ec *executionContext) field_Entity_findManyMultiPlanetRequiresNestedByName var arg0 []*model.MultiPlanetRequiresNestedByNamesInput if tmp, ok := rawArgs["reps"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reps")) - arg0, err = ec.unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInputᚄ(ctx, tmp) + arg0, err = ec.unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInput(ctx, tmp) if err != nil { return nil, err } @@ -7586,7 +7586,7 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti return res } -func (ec *executionContext) unmarshalNMultiHelloByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInputᚄ(ctx context.Context, v interface{}) ([]*model.MultiHelloByNamesInput, error) { +func (ec *executionContext) unmarshalNMultiHelloByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInput(ctx context.Context, v interface{}) ([]*model.MultiHelloByNamesInput, error) { var vSlice []interface{} if v != nil { vSlice = graphql.CoerceList(v) @@ -7595,7 +7595,7 @@ func (ec *executionContext) unmarshalNMultiHelloByNamesInput2ᚕᚖgithubᚗcom res := make([]*model.MultiHelloByNamesInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNMultiHelloByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalOMultiHelloByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7603,12 +7603,7 @@ func (ec *executionContext) unmarshalNMultiHelloByNamesInput2ᚕᚖgithubᚗcom return res, nil } -func (ec *executionContext) unmarshalNMultiHelloByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloByNamesInput, error) { - res, err := ec.unmarshalInputMultiHelloByNamesInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInputᚄ(ctx context.Context, v interface{}) ([]*model.MultiHelloMultipleRequiresByNamesInput, error) { +func (ec *executionContext) unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInput(ctx context.Context, v interface{}) ([]*model.MultiHelloMultipleRequiresByNamesInput, error) { var vSlice []interface{} if v != nil { vSlice = graphql.CoerceList(v) @@ -7617,7 +7612,7 @@ func (ec *executionContext) unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚕ res := make([]*model.MultiHelloMultipleRequiresByNamesInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalOMultiHelloMultipleRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7625,12 +7620,7 @@ func (ec *executionContext) unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚕ return res, nil } -func (ec *executionContext) unmarshalNMultiHelloMultipleRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloMultipleRequiresByNamesInput, error) { - res, err := ec.unmarshalInputMultiHelloMultipleRequiresByNamesInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) unmarshalNMultiHelloRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInputᚄ(ctx context.Context, v interface{}) ([]*model.MultiHelloRequiresByNamesInput, error) { +func (ec *executionContext) unmarshalNMultiHelloRequiresByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInput(ctx context.Context, v interface{}) ([]*model.MultiHelloRequiresByNamesInput, error) { var vSlice []interface{} if v != nil { vSlice = graphql.CoerceList(v) @@ -7639,7 +7629,7 @@ func (ec *executionContext) unmarshalNMultiHelloRequiresByNamesInput2ᚕᚖgithu res := make([]*model.MultiHelloRequiresByNamesInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNMultiHelloRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalOMultiHelloRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7647,12 +7637,7 @@ func (ec *executionContext) unmarshalNMultiHelloRequiresByNamesInput2ᚕᚖgithu return res, nil } -func (ec *executionContext) unmarshalNMultiHelloRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloRequiresByNamesInput, error) { - res, err := ec.unmarshalInputMultiHelloRequiresByNamesInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) unmarshalNMultiHelloWithErrorByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInputᚄ(ctx context.Context, v interface{}) ([]*model.MultiHelloWithErrorByNamesInput, error) { +func (ec *executionContext) unmarshalNMultiHelloWithErrorByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInput(ctx context.Context, v interface{}) ([]*model.MultiHelloWithErrorByNamesInput, error) { var vSlice []interface{} if v != nil { vSlice = graphql.CoerceList(v) @@ -7661,7 +7646,7 @@ func (ec *executionContext) unmarshalNMultiHelloWithErrorByNamesInput2ᚕᚖgith res := make([]*model.MultiHelloWithErrorByNamesInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNMultiHelloWithErrorByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalOMultiHelloWithErrorByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7669,12 +7654,7 @@ func (ec *executionContext) unmarshalNMultiHelloWithErrorByNamesInput2ᚕᚖgith return res, nil } -func (ec *executionContext) unmarshalNMultiHelloWithErrorByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloWithErrorByNamesInput, error) { - res, err := ec.unmarshalInputMultiHelloWithErrorByNamesInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInputᚄ(ctx context.Context, v interface{}) ([]*model.MultiPlanetRequiresNestedByNamesInput, error) { +func (ec *executionContext) unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInput(ctx context.Context, v interface{}) ([]*model.MultiPlanetRequiresNestedByNamesInput, error) { var vSlice []interface{} if v != nil { vSlice = graphql.CoerceList(v) @@ -7683,7 +7663,7 @@ func (ec *executionContext) unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚕ res := make([]*model.MultiPlanetRequiresNestedByNamesInput, len(vSlice)) for i := range vSlice { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) - res[i], err = ec.unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInput(ctx, vSlice[i]) + res[i], err = ec.unmarshalOMultiPlanetRequiresNestedByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInput(ctx, vSlice[i]) if err != nil { return nil, err } @@ -7691,11 +7671,6 @@ func (ec *executionContext) unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚕ return res, nil } -func (ec *executionContext) unmarshalNMultiPlanetRequiresNestedByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInput(ctx context.Context, v interface{}) (*model.MultiPlanetRequiresNestedByNamesInput, error) { - res, err := ec.unmarshalInputMultiPlanetRequiresNestedByNamesInput(ctx, v) - return &res, graphql.ErrorOnPath(ctx, err) -} - func (ec *executionContext) marshalNPlanetMultipleRequires2githubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐPlanetMultipleRequires(ctx context.Context, sel ast.SelectionSet, v model.PlanetMultipleRequires) graphql.Marshaler { return ec._PlanetMultipleRequires(ctx, sel, &v) } @@ -8239,6 +8214,14 @@ func (ec *executionContext) marshalOMultiHello2ᚖgithubᚗcomᚋ99designsᚋgql return ec._MultiHello(ctx, sel, v) } +func (ec *executionContext) unmarshalOMultiHelloByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloByNamesInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMultiHelloByNamesInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalOMultiHelloMultipleRequires2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequires(ctx context.Context, sel ast.SelectionSet, v []*model.MultiHelloMultipleRequires) graphql.Marshaler { if v == nil { return graphql.Null @@ -8287,6 +8270,14 @@ func (ec *executionContext) marshalOMultiHelloMultipleRequires2ᚖgithubᚗcom return ec._MultiHelloMultipleRequires(ctx, sel, v) } +func (ec *executionContext) unmarshalOMultiHelloMultipleRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloMultipleRequiresByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloMultipleRequiresByNamesInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMultiHelloMultipleRequiresByNamesInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalOMultiHelloRequires2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequires(ctx context.Context, sel ast.SelectionSet, v []*model.MultiHelloRequires) graphql.Marshaler { if v == nil { return graphql.Null @@ -8335,6 +8326,14 @@ func (ec *executionContext) marshalOMultiHelloRequires2ᚖgithubᚗcomᚋ99desig return ec._MultiHelloRequires(ctx, sel, v) } +func (ec *executionContext) unmarshalOMultiHelloRequiresByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloRequiresByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloRequiresByNamesInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMultiHelloRequiresByNamesInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalOMultiHelloWithError2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithError(ctx context.Context, sel ast.SelectionSet, v []*model.MultiHelloWithError) graphql.Marshaler { if v == nil { return graphql.Null @@ -8383,6 +8382,14 @@ func (ec *executionContext) marshalOMultiHelloWithError2ᚖgithubᚗcomᚋ99desi return ec._MultiHelloWithError(ctx, sel, v) } +func (ec *executionContext) unmarshalOMultiHelloWithErrorByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiHelloWithErrorByNamesInput(ctx context.Context, v interface{}) (*model.MultiHelloWithErrorByNamesInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMultiHelloWithErrorByNamesInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) marshalOMultiPlanetRequiresNested2ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNested(ctx context.Context, sel ast.SelectionSet, v []*model.MultiPlanetRequiresNested) graphql.Marshaler { if v == nil { return graphql.Null @@ -8431,6 +8438,14 @@ func (ec *executionContext) marshalOMultiPlanetRequiresNested2ᚖgithubᚗcomᚋ return ec._MultiPlanetRequiresNested(ctx, sel, v) } +func (ec *executionContext) unmarshalOMultiPlanetRequiresNestedByNamesInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋpluginᚋfederationᚋtestdataᚋentityresolverᚋgeneratedᚋmodelᚐMultiPlanetRequiresNestedByNamesInput(ctx context.Context, v interface{}) (*model.MultiPlanetRequiresNestedByNamesInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMultiPlanetRequiresNestedByNamesInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/plugin/federation/testdata/multi/multi.graphqls b/plugin/federation/testdata/multi/multi.graphqls new file mode 100644 index 0000000000..bf37c5a067 --- /dev/null +++ b/plugin/federation/testdata/multi/multi.graphqls @@ -0,0 +1,10 @@ +extend schema + @link(url: "https://specs.apollo.dev/federation/v2.3", + import: ["@key"]) + +directive @entityResolver(multi: Boolean) on OBJECT + +type Hello @key(fields: "name") @entityResolver(multi: true) { + name: String! + secondary: String! +} diff --git a/plugin/federation/testdata/multi/multi.yml b/plugin/federation/testdata/multi/multi.yml new file mode 100644 index 0000000000..891466c73f --- /dev/null +++ b/plugin/federation/testdata/multi/multi.yml @@ -0,0 +1,8 @@ +schema: + - "testdata/multi/multi.graphqls" +exec: + filename: testdata/multi/generated/exec.go +federation: + version: 2 + filename: testdata/multi/generated/federation.go +omit_slice_element_pointers: true \ No newline at end of file From 66709d89f0fd45eca823382d3a95020ef5c7485c Mon Sep 17 00:00:00 2001 From: gitxiongpan <45360805+gitxiongpan@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:10:50 +1000 Subject: [PATCH 38/54] feat: update getting-started CreateTodo mutationResolver (#2810) --- docs/content/getting-started.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index 985c16e031..ba3c442406 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -139,10 +139,10 @@ Returning to `graph/schema.resolvers.go`, let's implement the bodies of those au ```go func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { - rand, _ := rand.Int(rand.Reader, big.NewInt(100)) + randNumber, _ := rand.Int(rand.Reader, big.NewInt(100)) todo := &model.Todo{ Text: input.Text, - ID: fmt.Sprintf("T%d", rand), + ID: fmt.Sprintf("T%d", randNumber), User: &model.User{ID: input.UserID, Name: "user " + input.UserID}, } r.todos = append(r.todos, todo) @@ -250,10 +250,10 @@ And run `go run github.com/99designs/gqlgen generate`. Now if we look in `graph/schema.resolvers.go` we can see a new resolver, lets implement it and fix `CreateTodo`. ```go func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { + randNumber, _ := rand.Int(rand.Reader, big.NewInt(100)) todo := &model.Todo{ Text: input.Text, - ID: fmt.Sprintf("T%d", rand.Int()), - User: &model.User{ID: input.UserID, Name: "user " + input.UserID}, + ID: fmt.Sprintf("T%d", randNumber), UserID: input.UserID, } r.todos = append(r.todos, todo) From 4e8d8c70ce216824e506ad3d77b005f56c3ed144 Mon Sep 17 00:00:00 2001 From: Parker Roan <50146661+parkerroan@users.noreply.github.com> Date: Thu, 28 Sep 2023 07:11:35 -0500 Subject: [PATCH 39/54] Feature: Support Apollo Federation Auth Directives (#2809) * local version working * gofmt * tabs --- plugin/federation/federation.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugin/federation/federation.go b/plugin/federation/federation.go index 9df9b8a23f..99a1d312b0 100644 --- a/plugin/federation/federation.go +++ b/plugin/federation/federation.go @@ -59,6 +59,9 @@ func (f *federation) MutateConfig(cfg *config.Config) error { "_Any": { Model: config.StringList{"github.com/99designs/gqlgen/graphql.Map"}, }, + "federation__Scope": { + Model: config.StringList{"github.com/99designs/gqlgen/graphql.String"}, + }, } for typeName, entry := range builtins { @@ -80,6 +83,8 @@ func (f *federation) MutateConfig(cfg *config.Config) error { cfg.Directives["tag"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["override"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["inaccessible"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["authenticated"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["requiresScopes"] = config.DirectiveConfig{SkipRuntime: true} } return nil @@ -101,6 +106,7 @@ func (f *federation) InjectSourceEarly() *ast.Source { ` } else if f.Version == 2 { input += ` + directive @authenticated on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM directive @composeDirective(name: String!) repeatable on SCHEMA directive @extends on OBJECT | INTERFACE directive @external on OBJECT | FIELD_DEFINITION @@ -121,6 +127,12 @@ func (f *federation) InjectSourceEarly() *ast.Source { directive @override(from: String!) on FIELD_DEFINITION directive @provides(fields: FieldSet!) on FIELD_DEFINITION directive @requires(fields: FieldSet!) on FIELD_DEFINITION + directive @requiresScopes(scopes: [[federation__Scope!]!]!) on + | FIELD_DEFINITION + | OBJECT + | INTERFACE + | SCALAR + | ENUM directive @shareable repeatable on FIELD_DEFINITION | OBJECT directive @tag(name: String!) repeatable on | ARGUMENT_DEFINITION @@ -135,6 +147,7 @@ func (f *federation) InjectSourceEarly() *ast.Source { | UNION scalar _Any scalar FieldSet + scalar federation__Scope ` } return &ast.Source{ From f6fa3aae778926668b0787605c0eab125a800c1e Mon Sep 17 00:00:00 2001 From: Danny Shemesh Date: Thu, 28 Sep 2023 21:56:26 +0300 Subject: [PATCH 40/54] Consider go type name when autobinding (#2812) Currently, generated schema type names are normalized, for instance - SomeTYPE in the schema will be generated as SomeType in the model. When autobinding, however, we only consider the schema type name when searching for it in the relevant package(s), thus type names that differ post normalizations aren't auto-bound properly and are instead re-generated. This commit suggests a fix where we'd try to autobind for both the schema type name (first, to maintain back compat), or the go type name if the former isn't found. --- codegen/config/binder.go | 44 +-------- codegen/config/config.go | 23 ++++- codegen/config/config_test.go | 25 +++++ codegen/config/initialisms.go | 66 ++----------- codegen/config/initialisms_test.go | 6 +- .../autobinding/chat/{message.go => model.go} | 10 ++ codegen/templates/templates.go | 99 ++++++++++++++++++- 7 files changed, 165 insertions(+), 108 deletions(-) rename codegen/config/testdata/autobinding/chat/{message.go => model.go} (62%) diff --git a/codegen/config/binder.go b/codegen/config/binder.go index 0483afdbdf..22cc855db0 100644 --- a/codegen/config/binder.go +++ b/codegen/config/binder.go @@ -5,12 +5,12 @@ import ( "fmt" "go/token" "go/types" - "strings" + "github.com/vektah/gqlparser/v2/ast" "golang.org/x/tools/go/packages" + "github.com/99designs/gqlgen/codegen/templates" "github.com/99designs/gqlgen/internal/code" - "github.com/vektah/gqlparser/v2/ast" ) var ErrTypeNotFound = errors.New("unable to find type") @@ -285,7 +285,7 @@ func (ref *TypeReference) UniquenessKey() string { // Fix for #896 elemNullability = "ᚄ" } - return nullability + ref.Definition.Name + "2" + TypeIdentifier(ref.GO) + elemNullability + return nullability + ref.Definition.Name + "2" + templates.TypeIdentifier(ref.GO) + elemNullability } func (ref *TypeReference) MarshalFunc() string { @@ -540,41 +540,3 @@ func basicUnderlying(it types.Type) *types.Basic { return nil } - -var pkgReplacer = strings.NewReplacer( - "/", "ᚋ", - ".", "ᚗ", - "-", "ᚑ", - "~", "א", -) - -func TypeIdentifier(t types.Type) string { - res := "" - for { - switch it := t.(type) { - case *types.Pointer: - t.Underlying() - res += "ᚖ" - t = it.Elem() - case *types.Slice: - res += "ᚕ" - t = it.Elem() - case *types.Named: - res += pkgReplacer.Replace(it.Obj().Pkg().Path()) - res += "ᚐ" - res += it.Obj().Name() - return res - case *types.Basic: - res += it.Name() - return res - case *types.Map: - res += "map" - return res - case *types.Interface: - res += "interface" - return res - default: - panic(fmt.Errorf("unexpected type %T", it)) - } - } -} diff --git a/codegen/config/config.go b/codegen/config/config.go index 1e844f4696..50ccaeffda 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -3,6 +3,7 @@ package config import ( "bytes" "fmt" + "go/types" "io" "os" "path/filepath" @@ -10,10 +11,13 @@ import ( "sort" "strings" - "github.com/99designs/gqlgen/internal/code" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + "golang.org/x/tools/go/packages" "gopkg.in/yaml.v3" + + "github.com/99designs/gqlgen/codegen/templates" + "github.com/99designs/gqlgen/internal/code" ) type Config struct { @@ -608,8 +612,10 @@ func (c *Config) autobind() error { if p == nil || p.Module == nil { return fmt.Errorf("unable to load %s - make sure you're using an import path to a package that exists", c.AutoBind[i]) } - if t := p.Types.Scope().Lookup(t.Name); t != nil { - c.Models.Add(t.Name(), t.Pkg().Path()+"."+t.Name()) + + autobindType := c.lookupAutobindType(p, t) + if autobindType != nil { + c.Models.Add(t.Name, autobindType.Pkg().Path()+"."+autobindType.Name()) break } } @@ -643,6 +649,17 @@ func (c *Config) autobind() error { return nil } +func (c *Config) lookupAutobindType(p *packages.Package, schemaType *ast.Definition) types.Object { + // Try binding to either the original schema type name, or the normalized go type name + for _, lookupName := range []string{schemaType.Name, templates.ToGo(schemaType.Name)} { + if t := p.Types.Scope().Lookup(lookupName); t != nil { + return t + } + } + + return nil +} + func (c *Config) injectBuiltins() { builtins := TypeMap{ "__Directive": {Model: StringList{"github.com/99designs/gqlgen/graphql/introspection.Directive"}}, diff --git a/codegen/config/config_test.go b/codegen/config/config_test.go index 68e30d4b95..c8cb42ea3a 100644 --- a/codegen/config/config_test.go +++ b/codegen/config/config_test.go @@ -206,6 +206,31 @@ func TestAutobinding(t *testing.T) { require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", cfg.Models["Message"].Model[0]) }) + t.Run("normalized type names", func(t *testing.T) { + cfg := Config{ + Models: TypeMap{}, + AutoBind: []string{ + "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat", + "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/scalars/model", + }, + Packages: code.NewPackages(), + } + + cfg.Schema = gqlparser.MustLoadSchema(&ast.Source{Name: "TestAutobinding.schema", Input: ` + scalar Banned + type Message { id: ID } + enum ProductSKU { ProductSkuTrial } + type ChatAPI { id: ID } + `}) + + require.NoError(t, cfg.autobind()) + + require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/scalars/model.Banned", cfg.Models["Banned"].Model[0]) + require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.Message", cfg.Models["Message"].Model[0]) + require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.ProductSku", cfg.Models["ProductSKU"].Model[0]) + require.Equal(t, "github.com/99designs/gqlgen/codegen/config/testdata/autobinding/chat.ChatAPI", cfg.Models["ChatAPI"].Model[0]) + }) + t.Run("with file path", func(t *testing.T) { cfg := Config{ Models: TypeMap{}, diff --git a/codegen/config/initialisms.go b/codegen/config/initialisms.go index 5c169c8900..25e7331f8a 100644 --- a/codegen/config/initialisms.go +++ b/codegen/config/initialisms.go @@ -1,62 +1,10 @@ package config -import "strings" +import ( + "strings" -// commonInitialisms is a set of common initialisms. -// Only add entries that are highly unlikely to be non-initialisms. -// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. -var commonInitialisms = map[string]bool{ - "ACL": true, - "API": true, - "ASCII": true, - "CPU": true, - "CSS": true, - "CSV": true, - "DNS": true, - "EOF": true, - "GUID": true, - "HTML": true, - "HTTP": true, - "HTTPS": true, - "ICMP": true, - "ID": true, - "IP": true, - "JSON": true, - "KVK": true, - "LHS": true, - "PDF": true, - "PGP": true, - "QPS": true, - "QR": true, - "RAM": true, - "RHS": true, - "RPC": true, - "SLA": true, - "SMTP": true, - "SQL": true, - "SSH": true, - "SVG": true, - "TCP": true, - "TLS": true, - "TTL": true, - "UDP": true, - "UI": true, - "UID": true, - "URI": true, - "URL": true, - "UTF8": true, - "UUID": true, - "VM": true, - "XML": true, - "XMPP": true, - "XSRF": true, - "XSS": true, -} - -// GetInitialisms returns the initialisms to capitalize in Go names. If unchanged, default initialisms will be returned -var GetInitialisms = func() map[string]bool { - return commonInitialisms -} + "github.com/99designs/gqlgen/codegen/templates" +) // GoInitialismsConfig allows to modify the default behavior of naming Go methods, types and properties type GoInitialismsConfig struct { @@ -69,7 +17,7 @@ type GoInitialismsConfig struct { // setInitialisms adjustes GetInitialisms based on its settings. func (i GoInitialismsConfig) setInitialisms() { toUse := i.determineGoInitialisms() - GetInitialisms = func() map[string]bool { + templates.GetInitialisms = func() map[string]bool { return toUse } } @@ -82,8 +30,8 @@ func (i GoInitialismsConfig) determineGoInitialisms() (initialismsToUse map[stri initialismsToUse[strings.ToUpper(initialism)] = true } } else { - initialismsToUse = make(map[string]bool, len(commonInitialisms)+len(i.Initialisms)) - for initialism, value := range commonInitialisms { + initialismsToUse = make(map[string]bool, len(templates.CommonInitialisms)+len(i.Initialisms)) + for initialism, value := range templates.CommonInitialisms { initialismsToUse[strings.ToUpper(initialism)] = value } for _, initialism := range i.Initialisms { diff --git a/codegen/config/initialisms_test.go b/codegen/config/initialisms_test.go index 5bea561a3a..13c0da2465 100644 --- a/codegen/config/initialisms_test.go +++ b/codegen/config/initialisms_test.go @@ -5,6 +5,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/codegen/templates" ) func TestGoInitialismsConfig(t *testing.T) { @@ -17,12 +19,12 @@ func TestGoInitialismsConfig(t *testing.T) { t.Run("empty initialism config doesn't change anything", func(t *testing.T) { tt := GoInitialismsConfig{} result := tt.determineGoInitialisms() - assert.Equal(t, len(commonInitialisms), len(result)) + assert.Equal(t, len(templates.CommonInitialisms), len(result)) }) t.Run("initialism config appends if desired", func(t *testing.T) { tt := GoInitialismsConfig{ReplaceDefaults: false, Initialisms: []string{"ASDF"}} result := tt.determineGoInitialisms() - assert.Equal(t, len(commonInitialisms)+1, len(result)) + assert.Equal(t, len(templates.CommonInitialisms)+1, len(result)) assert.True(t, result["ASDF"]) }) t.Run("initialism config replaces if desired", func(t *testing.T) { diff --git a/codegen/config/testdata/autobinding/chat/message.go b/codegen/config/testdata/autobinding/chat/model.go similarity index 62% rename from codegen/config/testdata/autobinding/chat/message.go rename to codegen/config/testdata/autobinding/chat/model.go index b35be48c93..fa621ee90a 100644 --- a/codegen/config/testdata/autobinding/chat/message.go +++ b/codegen/config/testdata/autobinding/chat/model.go @@ -10,3 +10,13 @@ type Message struct { CreatedBy string `json:"createdBy"` CreatedAt time.Time `json:"createdAt"` } + +type ProductSku string + +const ( + ProductSkuTrial ProductSku = "Trial" +) + +type ChatAPI struct { + ID string `json:"id"` +} diff --git a/codegen/templates/templates.go b/codegen/templates/templates.go index 976527578d..4a4e91594e 100644 --- a/codegen/templates/templates.go +++ b/codegen/templates/templates.go @@ -17,7 +17,6 @@ import ( "text/template" "unicode" - "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/internal/code" "github.com/99designs/gqlgen/internal/imports" ) @@ -202,7 +201,7 @@ func Funcs() template.FuncMap { "rawQuote": rawQuote, "dump": Dump, "ref": ref, - "ts": config.TypeIdentifier, + "ts": TypeIdentifier, "call": Call, "prefixLines": prefixLines, "notNil": notNil, @@ -465,7 +464,7 @@ func wordWalker(str string, f func(*wordInfo)) { } i++ - initialisms := config.GetInitialisms() + initialisms := GetInitialisms() // [w,i) is a word. word := string(runes[w:i]) if !eow && initialisms[word] && !unicode.IsLower(runes[i]) { @@ -668,3 +667,97 @@ func write(filename string, b []byte, packages *code.Packages) error { return nil } + +var pkgReplacer = strings.NewReplacer( + "/", "ᚋ", + ".", "ᚗ", + "-", "ᚑ", + "~", "א", +) + +func TypeIdentifier(t types.Type) string { + res := "" + for { + switch it := t.(type) { + case *types.Pointer: + t.Underlying() + res += "ᚖ" + t = it.Elem() + case *types.Slice: + res += "ᚕ" + t = it.Elem() + case *types.Named: + res += pkgReplacer.Replace(it.Obj().Pkg().Path()) + res += "ᚐ" + res += it.Obj().Name() + return res + case *types.Basic: + res += it.Name() + return res + case *types.Map: + res += "map" + return res + case *types.Interface: + res += "interface" + return res + default: + panic(fmt.Errorf("unexpected type %T", it)) + } + } +} + +// CommonInitialisms is a set of common initialisms. +// Only add entries that are highly unlikely to be non-initialisms. +// For instance, "ID" is fine (Freudian code is rare), but "AND" is not. +var CommonInitialisms = map[string]bool{ + "ACL": true, + "API": true, + "ASCII": true, + "CPU": true, + "CSS": true, + "CSV": true, + "DNS": true, + "EOF": true, + "GUID": true, + "HTML": true, + "HTTP": true, + "HTTPS": true, + "ICMP": true, + "ID": true, + "IP": true, + "JSON": true, + "KVK": true, + "LHS": true, + "PDF": true, + "PGP": true, + "QPS": true, + "QR": true, + "RAM": true, + "RHS": true, + "RPC": true, + "SLA": true, + "SMTP": true, + "SQL": true, + "SSH": true, + "SVG": true, + "TCP": true, + "TLS": true, + "TTL": true, + "UDP": true, + "UI": true, + "UID": true, + "URI": true, + "URL": true, + "UTF8": true, + "UUID": true, + "VM": true, + "XML": true, + "XMPP": true, + "XSRF": true, + "XSS": true, +} + +// GetInitialisms returns the initialisms to capitalize in Go names. If unchanged, default initialisms will be returned +var GetInitialisms = func() map[string]bool { + return CommonInitialisms +} From 001c296a39ee981d415f5079ce0a8827e5d65874 Mon Sep 17 00:00:00 2001 From: Chris Pride Date: Fri, 29 Sep 2023 11:45:56 -0700 Subject: [PATCH 41/54] Update auto-generated files with latest results. (#2813) Co-authored-by: Chris Pride --- api/testdata/federation2/graph/generated.go | 87 +++++++++++++++++++ .../filetemplate/out/schema.custom.go | 2 +- .../followschema/out/schema.resolvers.go | 2 +- .../out/schema.resolvers.go | 2 +- .../resolvertemplate/out/schema.resolvers.go | 2 +- 5 files changed, 91 insertions(+), 4 deletions(-) diff --git a/api/testdata/federation2/graph/generated.go b/api/testdata/federation2/graph/generated.go index cc5924b8b1..ee351f30db 100644 --- a/api/testdata/federation2/graph/generated.go +++ b/api/testdata/federation2/graph/generated.go @@ -290,6 +290,7 @@ func sourceData(filename string) string { var sources = []*ast.Source{ {Name: "schema.graphqls", Input: sourceData("schema.graphqls"), BuiltIn: false}, {Name: "../federation/directives.graphql", Input: ` + directive @authenticated on FIELD_DEFINITION | OBJECT | INTERFACE | SCALAR | ENUM directive @composeDirective(name: String!) repeatable on SCHEMA directive @extends on OBJECT | INTERFACE directive @external on OBJECT | FIELD_DEFINITION @@ -310,6 +311,12 @@ var sources = []*ast.Source{ directive @override(from: String!) on FIELD_DEFINITION directive @provides(fields: FieldSet!) on FIELD_DEFINITION directive @requires(fields: FieldSet!) on FIELD_DEFINITION + directive @requiresScopes(scopes: [[federation__Scope!]!]!) on + | FIELD_DEFINITION + | OBJECT + | INTERFACE + | SCALAR + | ENUM directive @shareable repeatable on FIELD_DEFINITION | OBJECT directive @tag(name: String!) repeatable on | ARGUMENT_DEFINITION @@ -324,6 +331,7 @@ var sources = []*ast.Source{ | UNION scalar _Any scalar FieldSet + scalar federation__Scope `, BuiltIn: true}, {Name: "../federation/entity.graphql", Input: ` type _Service { @@ -3843,6 +3851,85 @@ func (ec *executionContext) marshalN__TypeKind2string(ctx context.Context, sel a return res } +func (ec *executionContext) unmarshalNfederation__Scope2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNfederation__Scope2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + +func (ec *executionContext) unmarshalNfederation__Scope2ᚕstringᚄ(ctx context.Context, v interface{}) ([]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNfederation__Scope2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNfederation__Scope2ᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNfederation__Scope2string(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNfederation__Scope2ᚕᚕstringᚄ(ctx context.Context, v interface{}) ([][]string, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([][]string, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNfederation__Scope2ᚕstringᚄ(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNfederation__Scope2ᚕᚕstringᚄ(ctx context.Context, sel ast.SelectionSet, v [][]string) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNfederation__Scope2ᚕstringᚄ(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + func (ec *executionContext) unmarshalOBoolean2bool(ctx context.Context, v interface{}) (bool, error) { res, err := graphql.UnmarshalBoolean(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go index 63da9a5e14..1727685b6d 100644 --- a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go +++ b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go @@ -2,7 +2,7 @@ package customresolver // 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.33-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go index 40c378b608..946520f85b 100644 --- a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go @@ -2,7 +2,7 @@ package customresolver // 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.33-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go b/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go index 31ce8f5741..7ae5c3e1ed 100644 --- a/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go @@ -2,7 +2,7 @@ package out // 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.33-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" diff --git a/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go b/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go index 17018884cb..4c5eded0f2 100644 --- a/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go @@ -2,7 +2,7 @@ package out // 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.35-dev +// Code generated by github.com/99designs/gqlgen version v0.17.38-dev import ( "context" From 919aded6be6cd722c202214e7a8183ed56762501 Mon Sep 17 00:00:00 2001 From: Chris Pride Date: Sat, 30 Sep 2023 04:08:45 -0700 Subject: [PATCH 42/54] Add a pong only keep alive for the new protcol (#2814) The protocol allows for this and this eliminates the potential for over-agressive triggers of the read deadline set for using the ping/pong flow. https://github.com/enisdenjo/graphql-ws/blob/50d5a512d0d7252d41c079e6716b884a191b1ddc/PROTOCOL.md#pong --- graphql/handler/transport/websocket.go | 26 ++++++++++++++- graphql/handler/transport/websocket_test.go | 35 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/graphql/handler/transport/websocket.go b/graphql/handler/transport/websocket.go index 8b375465c0..af35ad13e9 100644 --- a/graphql/handler/transport/websocket.go +++ b/graphql/handler/transport/websocket.go @@ -26,6 +26,7 @@ type ( ErrorFunc WebsocketErrorFunc CloseFunc WebsocketCloseFunc KeepAlivePingInterval time.Duration + PongOnlyInterval time.Duration PingPongInterval time.Duration didInjectSubprotocols bool @@ -38,6 +39,7 @@ type ( active map[string]context.CancelFunc mu sync.Mutex keepAliveTicker *time.Ticker + pongOnlyTicker *time.Ticker pingPongTicker *time.Ticker exec graphql.GraphExecutor closed bool @@ -239,8 +241,18 @@ func (c *wsConnection) run() { go c.keepAlive(ctx) } + // If we're running in graphql-transport-ws mode, create a timer that will trigger a + // just a pong message every interval + if c.conn.Subprotocol() == graphqltransportwsSubprotocol && c.PongOnlyInterval != 0 { + c.mu.Lock() + c.pongOnlyTicker = time.NewTicker(c.PongOnlyInterval) + c.mu.Unlock() + + go c.keepAlivePongOnly(ctx) + } + // If we're running in graphql-transport-ws mode, create a timer that will - // trigger a ping message every interval + // trigger a ping message every interval and expect a pong! if c.conn.Subprotocol() == graphqltransportwsSubprotocol && c.PingPongInterval != 0 { c.mu.Lock() c.pingPongTicker = time.NewTicker(c.PingPongInterval) @@ -292,6 +304,18 @@ func (c *wsConnection) run() { } } +func (c *wsConnection) keepAlivePongOnly(ctx context.Context) { + for { + select { + case <-ctx.Done(): + c.pongOnlyTicker.Stop() + return + case <-c.pongOnlyTicker.C: + c.write(&message{t: pongMessageType, payload: json.RawMessage{}}) + } + } +} + func (c *wsConnection) keepAlive(ctx context.Context) { for { select { diff --git a/graphql/handler/transport/websocket_test.go b/graphql/handler/transport/websocket_test.go index d7c0a4c743..cc4f42d1f8 100644 --- a/graphql/handler/transport/websocket_test.go +++ b/graphql/handler/transport/websocket_test.go @@ -692,6 +692,41 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) assert.Equal(t, connectionKeepAliveMsg, readOp(c).Type) }) + t.Run("pong only messages are sent when configured with graphql-transport-ws", func(t *testing.T) { + + h, srv := initialize(transport.Websocket{PongOnlyInterval: 10 * time.Millisecond}) + defer srv.Close() + + c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) + defer c.Close() + + require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) + + assert.Equal(t, graphqltransportwsPongMsg, readOp(c).Type) + + require.NoError(t, c.WriteJSON(&operationMessage{ + Type: graphqltransportwsSubscribeMsg, + ID: "test_1", + Payload: json.RawMessage(`{"query": "subscription { name }"}`), + })) + + // pong + msg := readOp(c) + assert.Equal(t, graphqltransportwsPongMsg, msg.Type) + + // server message + h.SendNextSubscriptionMessage() + msg = readOp(c) + require.Equal(t, graphqltransportwsNextMsg, msg.Type, string(msg.Payload)) + require.Equal(t, "test_1", msg.ID, string(msg.Payload)) + require.Equal(t, `{"data":{"name":"test"}}`, string(msg.Payload)) + + // keepalive + msg = readOp(c) + assert.Equal(t, graphqltransportwsPongMsg, msg.Type) + }) + } func wsConnect(url string) *websocket.Conn { From 89ac736ffe346e9ee95b12b4db467d1a802fe0ac Mon Sep 17 00:00:00 2001 From: gitxiongpan <45360805+gitxiongpan@users.noreply.github.com> Date: Mon, 2 Oct 2023 03:13:39 +1100 Subject: [PATCH 43/54] Store parsed Schema on ExecutableSchema rather than use global variable (#2811) * codegen: executableSchema schema configurable * feat * feat * codegen: add schema property on Config and executableSchema * fix: fmt * regenerate Signed-off-by: Steve Coffman --------- Signed-off-by: Steve Coffman Co-authored-by: Steve Coffman --- _examples/chat/generated.go | 10 ++++++++-- _examples/config/generated.go | 10 ++++++++-- _examples/dataloader/generated.go | 10 ++++++++-- _examples/embedding/subdir/gendir/generated.go | 10 ++++++++-- _examples/embedding/subdir/root_.generated.go | 10 ++++++++-- _examples/federation/accounts/graph/generated.go | 10 ++++++++-- _examples/federation/products/graph/generated.go | 10 ++++++++-- _examples/federation/reviews/graph/generated.go | 10 ++++++++-- _examples/fileupload/generated.go | 10 ++++++++-- _examples/scalars/generated.go | 10 ++++++++-- _examples/selection/generated.go | 10 ++++++++-- _examples/starwars/generated/exec.go | 10 ++++++++-- _examples/todo/generated.go | 10 ++++++++-- _examples/type-system-extension/generated.go | 10 ++++++++-- api/testdata/default/graph/generated.go | 10 ++++++++-- api/testdata/federation2/graph/generated.go | 10 ++++++++-- codegen/generated!.gotpl | 10 ++++++++-- codegen/root_.gotpl | 10 ++++++++-- codegen/testserver/followschema/root_.generated.go | 10 ++++++++-- codegen/testserver/singlefile/generated.go | 10 ++++++++-- integration/server/generated.go | 10 ++++++++-- .../testdata/entityresolver/generated/exec.go | 10 ++++++++-- .../testdata/filetemplate/out/schema.custom.go | 6 +++--- .../testdata/followschema/out/schema.resolvers.go | 6 +++--- 24 files changed, 182 insertions(+), 50 deletions(-) diff --git a/_examples/chat/generated.go b/_examples/chat/generated.go index 58f7545a7b..2ee09e11a2 100644 --- a/_examples/chat/generated.go +++ b/_examples/chat/generated.go @@ -25,6 +25,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -32,6 +33,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -84,12 +86,16 @@ type SubscriptionResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -288,14 +294,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" diff --git a/_examples/config/generated.go b/_examples/config/generated.go index 9d2a01c55a..b377298385 100644 --- a/_examples/config/generated.go +++ b/_examples/config/generated.go @@ -23,6 +23,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -30,6 +31,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -87,12 +89,16 @@ type RoleResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -278,14 +284,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" "todo.graphql" "user.graphql" diff --git a/_examples/dataloader/generated.go b/_examples/dataloader/generated.go index e205815208..b882fbc52c 100644 --- a/_examples/dataloader/generated.go +++ b/_examples/dataloader/generated.go @@ -24,6 +24,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -31,6 +32,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -91,12 +93,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -298,14 +304,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" diff --git a/_examples/embedding/subdir/gendir/generated.go b/_examples/embedding/subdir/gendir/generated.go index edb6ace6ba..eaf200d2dd 100644 --- a/_examples/embedding/subdir/gendir/generated.go +++ b/_examples/embedding/subdir/gendir/generated.go @@ -23,6 +23,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -30,6 +31,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -62,12 +64,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -189,14 +195,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } var sources = []*ast.Source{ diff --git a/_examples/embedding/subdir/root_.generated.go b/_examples/embedding/subdir/root_.generated.go index 03c8e18e5a..d2dc848a05 100644 --- a/_examples/embedding/subdir/root_.generated.go +++ b/_examples/embedding/subdir/root_.generated.go @@ -19,6 +19,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -26,6 +27,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -52,12 +54,16 @@ type ComplexityRoot struct { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -179,14 +185,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schemadir/root.graphqls" "subdir.graphqls" diff --git a/_examples/federation/accounts/graph/generated.go b/_examples/federation/accounts/graph/generated.go index 398daeacd9..791d5fa047 100644 --- a/_examples/federation/accounts/graph/generated.go +++ b/_examples/federation/accounts/graph/generated.go @@ -25,6 +25,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -32,6 +33,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -83,12 +85,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -274,14 +280,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphqls" diff --git a/_examples/federation/products/graph/generated.go b/_examples/federation/products/graph/generated.go index 15a66fb2cc..0f13b18d8f 100644 --- a/_examples/federation/products/graph/generated.go +++ b/_examples/federation/products/graph/generated.go @@ -25,6 +25,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -32,6 +33,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -86,12 +88,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -301,14 +307,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphqls" diff --git a/_examples/federation/reviews/graph/generated.go b/_examples/federation/reviews/graph/generated.go index ac7f09beab..79060f78c2 100644 --- a/_examples/federation/reviews/graph/generated.go +++ b/_examples/federation/reviews/graph/generated.go @@ -25,6 +25,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -32,6 +33,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -97,12 +99,16 @@ type UserResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -323,14 +329,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphqls" diff --git a/_examples/fileupload/generated.go b/_examples/fileupload/generated.go index f5730632e9..160ab84faa 100644 --- a/_examples/fileupload/generated.go +++ b/_examples/fileupload/generated.go @@ -24,6 +24,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -31,6 +32,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -75,12 +77,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -267,14 +273,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" diff --git a/_examples/scalars/generated.go b/_examples/scalars/generated.go index 94e57c0fa9..549d3a4fa5 100644 --- a/_examples/scalars/generated.go +++ b/_examples/scalars/generated.go @@ -26,6 +26,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -33,6 +34,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -84,12 +86,16 @@ type UserResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -305,14 +311,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" diff --git a/_examples/selection/generated.go b/_examples/selection/generated.go index b0f567eefd..a583e9edab 100644 --- a/_examples/selection/generated.go +++ b/_examples/selection/generated.go @@ -24,6 +24,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -31,6 +32,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -68,12 +70,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -223,14 +229,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" diff --git a/_examples/starwars/generated/exec.go b/_examples/starwars/generated/exec.go index b7a934bdab..1465c2bb43 100644 --- a/_examples/starwars/generated/exec.go +++ b/_examples/starwars/generated/exec.go @@ -24,6 +24,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -31,6 +32,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -146,12 +148,16 @@ type StarshipResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -581,14 +587,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } var sources = []*ast.Source{ diff --git a/_examples/todo/generated.go b/_examples/todo/generated.go index 8317645e00..0aa9e6c197 100644 --- a/_examples/todo/generated.go +++ b/_examples/todo/generated.go @@ -23,6 +23,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -30,6 +31,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -75,12 +77,16 @@ type MyQueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -259,14 +265,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphql" diff --git a/_examples/type-system-extension/generated.go b/_examples/type-system-extension/generated.go index 1fa0b781b2..71fb282a51 100644 --- a/_examples/type-system-extension/generated.go +++ b/_examples/type-system-extension/generated.go @@ -23,6 +23,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -30,6 +31,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -77,12 +79,16 @@ type MyQueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -245,14 +251,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schemas/enum-extension.graphql" "schemas/input-object-extension.graphql" "schemas/interface-extension.graphql" "schemas/object-extension.graphql" "schemas/scalar-extension.graphql" "schemas/schema-extension.graphql" "schemas/schema.graphql" "schemas/type-extension.graphql" "schemas/union-extension.graphql" diff --git a/api/testdata/default/graph/generated.go b/api/testdata/default/graph/generated.go index 386e78e65b..143fa7da3c 100644 --- a/api/testdata/default/graph/generated.go +++ b/api/testdata/default/graph/generated.go @@ -24,6 +24,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -31,6 +32,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -74,12 +76,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -244,14 +250,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphqls" diff --git a/api/testdata/federation2/graph/generated.go b/api/testdata/federation2/graph/generated.go index ee351f30db..7c3dc934ff 100644 --- a/api/testdata/federation2/graph/generated.go +++ b/api/testdata/federation2/graph/generated.go @@ -25,6 +25,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -32,6 +33,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -82,12 +84,16 @@ type QueryResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -266,14 +272,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema.graphqls" diff --git a/codegen/generated!.gotpl b/codegen/generated!.gotpl index 42e84b65da..b343e626d9 100644 --- a/codegen/generated!.gotpl +++ b/codegen/generated!.gotpl @@ -18,6 +18,7 @@ // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -25,6 +26,7 @@ } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -93,12 +95,16 @@ {{ if eq .Config.Exec.Layout "single-file" }} type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -268,14 +274,14 @@ if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } {{if .HasEmbeddableSources }} diff --git a/codegen/root_.gotpl b/codegen/root_.gotpl index dcfc84d0ed..0b90ad5356 100644 --- a/codegen/root_.gotpl +++ b/codegen/root_.gotpl @@ -17,6 +17,7 @@ // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -24,6 +25,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -66,12 +68,16 @@ type ComplexityRoot struct { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -241,14 +247,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } diff --git a/codegen/testserver/followschema/root_.generated.go b/codegen/testserver/followschema/root_.generated.go index 1d1d0ff5e8..467c7e981c 100644 --- a/codegen/testserver/followschema/root_.generated.go +++ b/codegen/testserver/followschema/root_.generated.go @@ -19,6 +19,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -26,6 +27,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -466,12 +468,16 @@ type ComplexityRoot struct { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -2202,14 +2208,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "builtinscalar.graphql" "complexity.graphql" "defaults.graphql" "defer.graphql" "directive.graphql" "embedded.graphql" "enum.graphql" "fields_order.graphql" "interfaces.graphql" "issue896.graphql" "loops.graphql" "maps.graphql" "mutation_with_custom_scalar.graphql" "nulls.graphql" "panics.graphql" "primitive_objects.graphql" "ptr_to_any.graphql" "ptr_to_ptr_input.graphql" "ptr_to_slice.graphql" "scalar_context.graphql" "scalar_default.graphql" "schema.graphql" "slices.graphql" "typefallback.graphql" "useptr.graphql" "v-ok.graphql" "validtypes.graphql" "variadic.graphql" "weird_type_cases.graphql" "wrapped_type.graphql" diff --git a/codegen/testserver/singlefile/generated.go b/codegen/testserver/singlefile/generated.go index 369cbf70d1..401b42a8fa 100644 --- a/codegen/testserver/singlefile/generated.go +++ b/codegen/testserver/singlefile/generated.go @@ -28,6 +28,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -35,6 +36,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -618,12 +620,16 @@ type FieldsOrderInputResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -2354,14 +2360,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "builtinscalar.graphql" "complexity.graphql" "defaults.graphql" "defer.graphql" "directive.graphql" "embedded.graphql" "enum.graphql" "fields_order.graphql" "interfaces.graphql" "issue896.graphql" "loops.graphql" "maps.graphql" "mutation_with_custom_scalar.graphql" "nulls.graphql" "panics.graphql" "primitive_objects.graphql" "ptr_to_any.graphql" "ptr_to_ptr_input.graphql" "ptr_to_slice.graphql" "scalar_context.graphql" "scalar_default.graphql" "schema.graphql" "slices.graphql" "typefallback.graphql" "useptr.graphql" "v-ok.graphql" "validtypes.graphql" "variadic.graphql" "weird_type_cases.graphql" "wrapped_type.graphql" diff --git a/integration/server/generated.go b/integration/server/generated.go index 6928d3f2d5..7b2c5c3ee1 100644 --- a/integration/server/generated.go +++ b/integration/server/generated.go @@ -26,6 +26,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -33,6 +34,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -99,12 +101,16 @@ type UserResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -319,14 +325,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } //go:embed "schema/schema.graphql" "schema/testomitempty.graphql" "schema/user.graphql" diff --git a/plugin/federation/testdata/entityresolver/generated/exec.go b/plugin/federation/testdata/entityresolver/generated/exec.go index 20ed74ad93..25a9f93d9b 100644 --- a/plugin/federation/testdata/entityresolver/generated/exec.go +++ b/plugin/federation/testdata/entityresolver/generated/exec.go @@ -24,6 +24,7 @@ import ( // NewExecutableSchema creates an ExecutableSchema from the ResolverRoot interface. func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { return &executableSchema{ + schema: cfg.Schema, resolvers: cfg.Resolvers, directives: cfg.Directives, complexity: cfg.Complexity, @@ -31,6 +32,7 @@ func NewExecutableSchema(cfg Config) graphql.ExecutableSchema { } type Config struct { + Schema *ast.Schema Resolvers ResolverRoot Directives DirectiveRoot Complexity ComplexityRoot @@ -168,12 +170,16 @@ type EntityResolver interface { } type executableSchema struct { + schema *ast.Schema resolvers ResolverRoot directives DirectiveRoot complexity ComplexityRoot } func (e *executableSchema) Schema() *ast.Schema { + if e.schema != nil { + return e.schema + } return parsedSchema } @@ -710,14 +716,14 @@ func (ec *executionContext) introspectSchema() (*introspection.Schema, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapSchema(parsedSchema), nil + return introspection.WrapSchema(ec.Schema()), nil } func (ec *executionContext) introspectType(name string) (*introspection.Type, error) { if ec.DisableIntrospection { return nil, errors.New("introspection disabled") } - return introspection.WrapTypeFromDef(parsedSchema, parsedSchema.Types[name]), nil + return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } var sources = []*ast.Source{ diff --git a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go index 1727685b6d..2b0888d10b 100644 --- a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go +++ b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go @@ -36,9 +36,9 @@ type resolverCustomResolverType struct{ *CustomResolverType } // !!! WARNING !!! // The code below was going to be deleted when updating resolvers. It has been copied here so you have // one last chance to move it out of harms way if you want. There are two reasons this happens: -// - When renaming or deleting a resolver the old code will be put in here. You can safely delete -// it when you're done. -// - You have helper methods in this file. Move them out to keep these resolver files clean. +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. func AUserHelperFunction() { // AUserHelperFunction implementation } diff --git a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go index 946520f85b..87d3aab316 100644 --- a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go @@ -36,9 +36,9 @@ type resolverCustomResolverType struct{ *CustomResolverType } // !!! WARNING !!! // The code below was going to be deleted when updating resolvers. It has been copied here so you have // one last chance to move it out of harms way if you want. There are two reasons this happens: -// - When renaming or deleting a resolver the old code will be put in here. You can safely delete -// it when you're done. -// - You have helper methods in this file. Move them out to keep these resolver files clean. +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. func AUserHelperFunction() { // AUserHelperFunction implementation } From 37f8e4ebb45d5a7edac5e8f6a241d842b4b9cfb1 Mon Sep 17 00:00:00 2001 From: Chris Pride Date: Sun, 1 Oct 2023 09:23:32 -0700 Subject: [PATCH 44/54] Add ability to not fail when pong is not received. (#2815) I also changed how the read deadline set works a little, the reason for this is that the protocol allows for pong to be sent without a ping. So setting a read deadline on receiving pong isn't great. Instead we should always set the read deadline on sending ping. Though to do this we need to know whether we have received a pong or not. Because if we set the read deadline when the previous ping still hasn't received the pong. Then it will never hit the deadline. --- graphql/handler/transport/websocket.go | 32 ++++++++-- graphql/handler/transport/websocket_test.go | 68 ++++++++++++++++++++- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/graphql/handler/transport/websocket.go b/graphql/handler/transport/websocket.go index af35ad13e9..1969f9e285 100644 --- a/graphql/handler/transport/websocket.go +++ b/graphql/handler/transport/websocket.go @@ -28,6 +28,15 @@ type ( KeepAlivePingInterval time.Duration PongOnlyInterval time.Duration PingPongInterval time.Duration + /* If PingPongInterval has a non-0 duration, then when the server sends a ping + * it sets a ReadDeadline of PingPongInterval*2 and if the client doesn't respond + * with pong before that deadline is reached then the connection will die with a + * 1006 error code. + * + * MissingPongOk if true, tells the server to not use a ReadDeadline such that a + * missing/slow pong response from the client doesn't kill the connection. + */ + MissingPongOk bool didInjectSubprotocols bool } @@ -41,6 +50,7 @@ type ( keepAliveTicker *time.Ticker pongOnlyTicker *time.Ticker pingPongTicker *time.Ticker + receivedPong bool exec graphql.GraphExecutor closed bool @@ -258,9 +268,11 @@ func (c *wsConnection) run() { c.pingPongTicker = time.NewTicker(c.PingPongInterval) c.mu.Unlock() - // Note: when the connection is closed by this deadline, the client - // will receive an "invalid close code" - c.conn.SetReadDeadline(time.Now().UTC().Add(2 * c.PingPongInterval)) + if !c.MissingPongOk { + // Note: when the connection is closed by this deadline, the client + // will receive an "invalid close code" + c.conn.SetReadDeadline(time.Now().UTC().Add(2 * c.PingPongInterval)) + } go c.ping(ctx) } @@ -295,7 +307,11 @@ func (c *wsConnection) run() { case pingMessageType: c.write(&message{t: pongMessageType, payload: m.payload}) case pongMessageType: - c.conn.SetReadDeadline(time.Now().UTC().Add(2 * c.PingPongInterval)) + c.mu.Lock() + c.receivedPong = true + c.mu.Unlock() + // Clear ReadTimeout -- 0 time val clears. + c.conn.SetReadDeadline(time.Time{}) default: c.sendConnectionError("unexpected message %s", m.t) c.close(websocket.CloseProtocolError, "unexpected message") @@ -336,6 +352,14 @@ func (c *wsConnection) ping(ctx context.Context) { return case <-c.pingPongTicker.C: c.write(&message{t: pingMessageType, payload: json.RawMessage{}}) + // The initial deadline for this method is set in run() + // if we have not yet received a pong, don't reset the deadline. + c.mu.Lock() + if !c.MissingPongOk && c.receivedPong { + c.conn.SetReadDeadline(time.Now().UTC().Add(2 * c.PingPongInterval)) + } + c.receivedPong = false + c.mu.Unlock() } } } diff --git a/graphql/handler/transport/websocket_test.go b/graphql/handler/transport/websocket_test.go index cc4f42d1f8..f05a9df189 100644 --- a/graphql/handler/transport/websocket_test.go +++ b/graphql/handler/transport/websocket_test.go @@ -638,7 +638,7 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { } t.Run("client receives ping and responds with pong", func(t *testing.T) { - _, srv := initialize(transport.Websocket{PingPongInterval: 10 * time.Millisecond}) + _, srv := initialize(transport.Websocket{PingPongInterval: 20 * time.Millisecond}) defer srv.Close() c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) @@ -652,6 +652,11 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { assert.Equal(t, graphqltransportwsPingMsg, readOp(c).Type) }) + t.Run("client sends ping and expects pong", func(t *testing.T) { + _, srv := initialize(transport.Websocket{PingPongInterval: 10 * time.Millisecond}) + defer srv.Close() + }) + t.Run("client sends ping and expects pong", func(t *testing.T) { _, srv := initialize(transport.Websocket{PingPongInterval: 10 * time.Millisecond}) defer srv.Close() @@ -666,6 +671,67 @@ func TestWebsocketWithPingPongInterval(t *testing.T) { assert.Equal(t, graphqltransportwsPongMsg, readOp(c).Type) }) + t.Run("server closes with error if client does not pong and !MissingPongOk", func(t *testing.T) { + h := testserver.New() + closeFuncCalled := make(chan bool, 1) + h.AddTransport(transport.Websocket{ + MissingPongOk: false, // default value but beign explicit for test clarity. + PingPongInterval: 5 * time.Millisecond, + CloseFunc: func(_ context.Context, _closeCode int) { + closeFuncCalled <- true + }, + }) + + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) + defer c.Close() + + require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) + + assert.Equal(t, graphqltransportwsPingMsg, readOp(c).Type) + + select { + case res := <-closeFuncCalled: + assert.True(t, res) + case <-time.NewTimer(time.Millisecond * 20).C: + // with a 5ms interval 10ms should be the timeout, double that to make the test less likely to flake under load + assert.Fail(t, "The close handler was not called in time") + } + }) + + t.Run("server does not close with error if client does not pong and MissingPongOk", func(t *testing.T) { + h := testserver.New() + closeFuncCalled := make(chan bool, 1) + h.AddTransport(transport.Websocket{ + MissingPongOk: true, + PingPongInterval: 10 * time.Millisecond, + CloseFunc: func(_ context.Context, _closeCode int) { + closeFuncCalled <- true + }, + }) + + srv := httptest.NewServer(h) + defer srv.Close() + + c := wsConnectWithSubprocotol(srv.URL, graphqltransportwsSubprotocol) + defer c.Close() + + require.NoError(t, c.WriteJSON(&operationMessage{Type: graphqltransportwsConnectionInitMsg})) + assert.Equal(t, graphqltransportwsConnectionAckMsg, readOp(c).Type) + + assert.Equal(t, graphqltransportwsPingMsg, readOp(c).Type) + + select { + case <-closeFuncCalled: + assert.Fail(t, "The close handler was called even with MissingPongOk = true") + case _, ok := <-time.NewTimer(time.Millisecond * 20).C: + assert.True(t, ok) + } + }) + t.Run("ping-pongs are not sent when the graphql-ws sub protocol is used", func(t *testing.T) { // Regression test // --- From 5925864212bb286e22a3027c3900aa99874cc7ad Mon Sep 17 00:00:00 2001 From: Rodrigo Boratto Date: Tue, 3 Oct 2023 12:35:34 -0300 Subject: [PATCH 45/54] Adding duration scalar conforming to ISO8601 standard (#2800) * Adding duration scalar * simple Duration scalar docs * using MarshalString, to add proper double quotes * adding deps and running go mod tidy on _examples * Re-organize imports Signed-off-by: Steve Coffman * Fix test now that imports are sorted Signed-off-by: Steve Coffman --------- Signed-off-by: Steve Coffman Co-authored-by: Steve Coffman --- _examples/chat/chat_test.go | 5 ++-- _examples/chat/server/server.go | 8 +++--- _examples/dataloader/dataloader_test.go | 3 ++- _examples/embedding/subdir/embedding_test.go | 3 ++- _examples/fileupload/fileupload_test.go | 3 ++- _examples/fileupload/server/server.go | 8 +++--- _examples/go.mod | 1 + _examples/go.sum | 2 ++ _examples/scalars/scalar_test.go | 3 ++- _examples/selection/selection.go | 3 ++- _examples/selection/selection_test.go | 3 ++- _examples/starwars/resolvers.go | 1 - _examples/starwars/starwars_test.go | 3 ++- _examples/todo/todo.go | 3 ++- _examples/todo/todo_test.go | 3 ++- .../type-system-extension/server/server.go | 3 +-- _examples/websocket-initfunc/server/server.go | 9 ++++--- api/generate_test.go | 3 ++- api/option_test.go | 3 ++- client/client_test.go | 3 ++- client/withfilesoption_test.go | 3 ++- codegen/args.go | 3 ++- codegen/config/binder_test.go | 4 +-- codegen/data_test.go | 4 +-- codegen/directive.go | 3 ++- codegen/field.go | 5 ++-- codegen/field_test.go | 3 ++- codegen/generate.go | 3 ++- codegen/object.go | 3 ++- codegen/templates/import_test.go | 4 +-- codegen/templates/templates_test.go | 4 +-- .../followschema/complexity_test.go | 3 ++- .../testserver/followschema/defaults_test.go | 3 ++- .../testserver/followschema/directive_test.go | 3 ++- .../testserver/followschema/embedded_test.go | 3 ++- codegen/testserver/followschema/enums_test.go | 3 ++- .../followschema/fields_order_test.go | 3 ++- .../testserver/followschema/generated_test.go | 3 ++- codegen/testserver/followschema/input_test.go | 3 ++- .../followschema/interfaces_test.go | 3 ++- .../followschema/introspection_test.go | 3 ++- codegen/testserver/followschema/maps_test.go | 3 ++- .../followschema/middleware_test.go | 6 ++--- .../followschema/modelmethod_test.go | 3 ++- .../mutation_with_custom_scalar_test.go | 3 ++- codegen/testserver/followschema/nulls_test.go | 3 ++- .../testserver/followschema/panics_test.go | 6 ++--- .../followschema/primitive_objects_test.go | 3 ++- .../followschema/ptr_to_any_test.go | 3 ++- .../followschema/ptr_to_ptr_input_test.go | 3 ++- .../followschema/ptr_to_slice_test.go | 3 ++- .../followschema/response_extension_test.go | 3 ++- .../followschema/scalar_context_test.go | 3 ++- .../followschema/scalar_default_test.go | 3 ++- .../testserver/followschema/slices_test.go | 3 ++- .../followschema/subscription_test.go | 4 +-- codegen/testserver/followschema/time_test.go | 3 ++- .../followschema/typefallback_test.go | 3 ++- .../followschema/validtypes_test.go | 3 ++- .../followschema/wrapped_type_test.go | 3 ++- .../testserver/singlefile/complexity_test.go | 3 ++- .../testserver/singlefile/defaults_test.go | 3 ++- codegen/testserver/singlefile/defer_test.go | 5 ++-- .../testserver/singlefile/directive_test.go | 3 ++- .../testserver/singlefile/embedded_test.go | 3 ++- codegen/testserver/singlefile/enums_test.go | 3 ++- .../singlefile/fields_order_test.go | 3 ++- .../testserver/singlefile/generated_test.go | 3 ++- codegen/testserver/singlefile/input_test.go | 3 ++- .../testserver/singlefile/interfaces_test.go | 3 ++- .../singlefile/introspection_test.go | 3 ++- codegen/testserver/singlefile/maps_test.go | 3 ++- .../testserver/singlefile/middleware_test.go | 6 ++--- .../testserver/singlefile/modelmethod_test.go | 3 ++- .../mutation_with_custom_scalar_test.go | 3 ++- codegen/testserver/singlefile/nulls_test.go | 3 ++- codegen/testserver/singlefile/panics_test.go | 6 ++--- .../singlefile/primitive_objects_test.go | 3 ++- .../testserver/singlefile/ptr_to_any_test.go | 3 ++- .../singlefile/ptr_to_ptr_input_test.go | 3 ++- .../singlefile/ptr_to_slice_test.go | 3 ++- .../singlefile/response_extension_test.go | 3 ++- .../singlefile/scalar_context_test.go | 3 ++- .../singlefile/scalar_default_test.go | 3 ++- codegen/testserver/singlefile/slices_test.go | 3 ++- .../singlefile/subscription_test.go | 4 +-- codegen/testserver/singlefile/time_test.go | 3 ++- .../singlefile/typefallback_test.go | 3 ++- .../testserver/singlefile/validtypes_test.go | 3 ++- .../singlefile/wrapped_type_test.go | 3 ++- complexity/complexity.go | 3 ++- complexity/complexity_test.go | 3 ++- docs/content/reference/scalars.md | 17 ++++++++++++ go.mod | 1 + go.sum | 2 ++ graphql/duration.go | 27 +++++++++++++++++++ graphql/duration_test.go | 26 ++++++++++++++++++ graphql/executor/executor.go | 5 ++-- graphql/executor/executor_test.go | 7 ++--- graphql/executor/testexecutor/testexecutor.go | 5 ++-- .../apollofederatedtracingv1/tracing.go | 3 ++- .../apollofederatedtracingv1/tracing_test.go | 9 ++++--- .../apollofederatedtracingv1/tree_builder.go | 3 ++- graphql/handler/apollotracing/tracer.go | 3 ++- graphql/handler/apollotracing/tracer_test.go | 9 ++++--- graphql/handler/extension/apq.go | 5 ++-- graphql/handler/extension/apq_test.go | 3 ++- graphql/handler/extension/complexity.go | 3 ++- graphql/handler/extension/complexity_test.go | 3 ++- graphql/handler/extension/introspection.go | 3 ++- .../handler/extension/introspection_test.go | 3 ++- graphql/handler/lru/lru.go | 3 ++- graphql/handler/server.go | 3 ++- graphql/handler/server_test.go | 7 ++--- graphql/handler/testserver/testserver.go | 5 ++-- graphql/handler/transport/error.go | 3 ++- graphql/handler/transport/headers_test.go | 9 ++++--- .../transport/http_form_multipart_test.go | 7 ++--- .../transport/http_form_urlencode_test.go | 3 ++- graphql/handler/transport/http_get.go | 5 ++-- graphql/handler/transport/http_get_test.go | 3 ++- .../handler/transport/http_graphql_test.go | 3 ++- graphql/handler/transport/http_post_test.go | 3 ++- graphql/handler/transport/util.go | 3 ++- graphql/handler/transport/websocket.go | 5 ++-- graphql/handler/transport/websocket_test.go | 11 ++++---- handler/handler.go | 3 ++- integration/server/cmd/integration/server.go | 3 ++- internal/imports/prune.go | 4 +-- internal/imports/prune_test.go | 3 ++- internal/imports/testdata/unused.expected.go | 1 + internal/imports/testdata/unused.go | 1 + internal/rewrite/rewriter.go | 3 ++- internal/rewrite/rewriter_test.go | 8 +++--- internal/rewrite/testdata/example.go | 3 +-- main.go | 3 ++- plugin/federation/entity.go | 3 ++- .../federation_entityresolver_test.go | 4 +-- plugin/federation/federation_test.go | 3 ++- plugin/federation/fieldset/fieldset.go | 3 ++- plugin/modelgen/models.go | 3 ++- plugin/modelgen/models_test.go | 5 ++-- plugin/plugin.go | 3 ++- plugin/resolvergen/resolver_test.go | 5 ++-- plugin/stubgen/stubs.go | 3 +-- 145 files changed, 385 insertions(+), 200 deletions(-) create mode 100644 graphql/duration.go create mode 100644 graphql/duration_test.go diff --git a/_examples/chat/chat_test.go b/_examples/chat/chat_test.go index 8a4081bdb8..c3dd59abee 100644 --- a/_examples/chat/chat_test.go +++ b/_examples/chat/chat_test.go @@ -6,10 +6,11 @@ import ( "sync" "testing" - "github.com/99designs/gqlgen/client" - "github.com/99designs/gqlgen/graphql/handler" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" ) func TestChatSubscriptions(t *testing.T) { diff --git a/_examples/chat/server/server.go b/_examples/chat/server/server.go index 19e938f340..5627f4d2a0 100644 --- a/_examples/chat/server/server.go +++ b/_examples/chat/server/server.go @@ -6,11 +6,6 @@ import ( "net/url" "time" - "github.com/99designs/gqlgen/graphql/handler/extension" - "github.com/99designs/gqlgen/graphql/handler/transport" - - "github.com/99designs/gqlgen/graphql/playground" - "github.com/gorilla/websocket" "github.com/opentracing/opentracing-go" "github.com/rs/cors" @@ -20,6 +15,9 @@ import ( "github.com/99designs/gqlgen/_examples/chat" "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/99designs/gqlgen/graphql/playground" ) func main() { diff --git a/_examples/dataloader/dataloader_test.go b/_examples/dataloader/dataloader_test.go index c70b45b95a..34dc9e427d 100644 --- a/_examples/dataloader/dataloader_test.go +++ b/_examples/dataloader/dataloader_test.go @@ -3,10 +3,11 @@ package dataloader import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/introspection" - "github.com/stretchr/testify/require" ) func TestTodo(t *testing.T) { diff --git a/_examples/embedding/subdir/embedding_test.go b/_examples/embedding/subdir/embedding_test.go index d779455236..3f2e97d24c 100644 --- a/_examples/embedding/subdir/embedding_test.go +++ b/_examples/embedding/subdir/embedding_test.go @@ -3,10 +3,11 @@ package subdir import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/_examples/embedding/subdir/gendir" "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestEmbeddingWorks(t *testing.T) { diff --git a/_examples/fileupload/fileupload_test.go b/_examples/fileupload/fileupload_test.go index 29ef9dc3fb..c4138c14c9 100644 --- a/_examples/fileupload/fileupload_test.go +++ b/_examples/fileupload/fileupload_test.go @@ -8,12 +8,13 @@ import ( "os" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/_examples/fileupload/model" gqlclient "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/require" ) func TestFileUpload(t *testing.T) { diff --git a/_examples/fileupload/server/server.go b/_examples/fileupload/server/server.go index 75a47b73b6..55dc08d883 100644 --- a/_examples/fileupload/server/server.go +++ b/_examples/fileupload/server/server.go @@ -7,15 +7,13 @@ import ( "log" "net/http" - "github.com/99designs/gqlgen/graphql/handler/extension" - "github.com/99designs/gqlgen/graphql/handler/transport" - - "github.com/99designs/gqlgen/graphql/playground" - "github.com/99designs/gqlgen/_examples/fileupload" "github.com/99designs/gqlgen/_examples/fileupload/model" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/99designs/gqlgen/graphql/playground" ) func main() { diff --git a/_examples/go.mod b/_examples/go.mod index bd3fcb10bc..b6dfdaa00b 100644 --- a/_examples/go.mod +++ b/_examples/go.mod @@ -25,6 +25,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sosodev/duration v1.1.0 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/tools v0.9.3 // indirect diff --git a/_examples/go.sum b/_examples/go.sum index 0efcf708e3..98f0ac96a2 100644 --- a/_examples/go.sum +++ b/_examples/go.sum @@ -48,6 +48,8 @@ github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06B github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU= github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sosodev/duration v1.1.0 h1:kQcaiGbJaIsRqgQy7VGlZrVw1giWO+lDoX3MCPnpVO4= +github.com/sosodev/duration v1.1.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= 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= diff --git a/_examples/scalars/scalar_test.go b/_examples/scalars/scalar_test.go index f9ca2b1dd1..0d3228b141 100644 --- a/_examples/scalars/scalar_test.go +++ b/_examples/scalars/scalar_test.go @@ -4,10 +4,11 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/introspection" - "github.com/stretchr/testify/require" ) type RawUser struct { diff --git a/_examples/selection/selection.go b/_examples/selection/selection.go index 5890d14ab9..6a6b0f9bec 100644 --- a/_examples/selection/selection.go +++ b/_examples/selection/selection.go @@ -7,8 +7,9 @@ import ( "fmt" "time" - "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" ) type Resolver struct{} diff --git a/_examples/selection/selection_test.go b/_examples/selection/selection_test.go index c687403322..72495e927b 100644 --- a/_examples/selection/selection_test.go +++ b/_examples/selection/selection_test.go @@ -3,9 +3,10 @@ package selection import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestSelection(t *testing.T) { diff --git a/_examples/starwars/resolvers.go b/_examples/starwars/resolvers.go index e7b9629d12..6c94a2ea0f 100644 --- a/_examples/starwars/resolvers.go +++ b/_examples/starwars/resolvers.go @@ -12,7 +12,6 @@ import ( "time" "github.com/99designs/gqlgen/_examples/starwars/generated" - "github.com/99designs/gqlgen/_examples/starwars/models" ) diff --git a/_examples/starwars/starwars_test.go b/_examples/starwars/starwars_test.go index 8cbe861b0c..a01f9fb7b5 100644 --- a/_examples/starwars/starwars_test.go +++ b/_examples/starwars/starwars_test.go @@ -3,11 +3,12 @@ package starwars import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/_examples/starwars/generated" "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/introspection" - "github.com/stretchr/testify/require" ) func TestStarwars(t *testing.T) { diff --git a/_examples/todo/todo.go b/_examples/todo/todo.go index ad3da2c392..f8a710722e 100644 --- a/_examples/todo/todo.go +++ b/_examples/todo/todo.go @@ -8,8 +8,9 @@ import ( "fmt" "time" - "github.com/99designs/gqlgen/graphql" "github.com/mitchellh/mapstructure" + + "github.com/99designs/gqlgen/graphql" ) var ( diff --git a/_examples/todo/todo_test.go b/_examples/todo/todo_test.go index a6cef4ac05..348ecc7023 100644 --- a/_examples/todo/todo_test.go +++ b/_examples/todo/todo_test.go @@ -3,10 +3,11 @@ package todo import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/introspection" - "github.com/stretchr/testify/require" ) func TestTodo(t *testing.T) { diff --git a/_examples/type-system-extension/server/server.go b/_examples/type-system-extension/server/server.go index 2ddca5f7b9..6fec1d2403 100644 --- a/_examples/type-system-extension/server/server.go +++ b/_examples/type-system-extension/server/server.go @@ -5,10 +5,9 @@ import ( "net/http" "os" - "github.com/99designs/gqlgen/graphql/playground" - extension "github.com/99designs/gqlgen/_examples/type-system-extension" "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" ) const defaultPort = "8080" diff --git a/_examples/websocket-initfunc/server/server.go b/_examples/websocket-initfunc/server/server.go index 64c3010f81..7027e9728e 100644 --- a/_examples/websocket-initfunc/server/server.go +++ b/_examples/websocket-initfunc/server/server.go @@ -8,14 +8,15 @@ import ( "os" "time" - "github.com/99designs/gqlgen/graphql/handler" - "github.com/99designs/gqlgen/graphql/handler/extension" - "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/99designs/gqlgen/graphql/playground" "github.com/go-chi/chi" "github.com/gorilla/websocket" "github.com/gqlgen/_examples/websocket-initfunc/server/graph" "github.com/rs/cors" + + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/extension" + "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/99designs/gqlgen/graphql/playground" ) func webSocketInit(ctx context.Context, initPayload transport.InitPayload) (context.Context, *transport.InitPayload, error) { diff --git a/api/generate_test.go b/api/generate_test.go index 417e6f3060..7778f95343 100644 --- a/api/generate_test.go +++ b/api/generate_test.go @@ -5,8 +5,9 @@ import ( "path" "testing" - "github.com/99designs/gqlgen/codegen/config" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/codegen/config" ) func cleanup(workDir string) { diff --git a/api/option_test.go b/api/option_test.go index 5819c4bdd0..d84da902fd 100644 --- a/api/option_test.go +++ b/api/option_test.go @@ -3,12 +3,13 @@ package api import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/plugin" "github.com/99designs/gqlgen/plugin/federation" "github.com/99designs/gqlgen/plugin/modelgen" "github.com/99designs/gqlgen/plugin/resolvergen" - "github.com/stretchr/testify/require" ) type testPlugin struct{} diff --git a/client/client_test.go b/client/client_test.go index 4755ca5fa8..d7b95dcae2 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -12,9 +12,10 @@ import ( "testing" "time" - "github.com/99designs/gqlgen/client" "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/client" ) func TestClient(t *testing.T) { diff --git a/client/withfilesoption_test.go b/client/withfilesoption_test.go index dbb7756cd7..054c3622fe 100644 --- a/client/withfilesoption_test.go +++ b/client/withfilesoption_test.go @@ -10,8 +10,9 @@ import ( "strings" "testing" - "github.com/99designs/gqlgen/client" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/client" ) func TestWithFiles(t *testing.T) { diff --git a/codegen/args.go b/codegen/args.go index c4cecea932..2f174332c7 100644 --- a/codegen/args.go +++ b/codegen/args.go @@ -5,9 +5,10 @@ import ( "go/types" "strings" + "github.com/vektah/gqlparser/v2/ast" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" - "github.com/vektah/gqlparser/v2/ast" ) type ArgSet struct { diff --git a/codegen/config/binder_test.go b/codegen/config/binder_test.go index ae6b3027fb..f436a8efe3 100644 --- a/codegen/config/binder_test.go +++ b/codegen/config/binder_test.go @@ -4,11 +4,11 @@ import ( "go/types" "testing" - "github.com/99designs/gqlgen/internal/code" - "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/internal/code" ) func TestBindingToInvalid(t *testing.T) { diff --git a/codegen/data_test.go b/codegen/data_test.go index a1ac4d3df9..64ca8c621f 100644 --- a/codegen/data_test.go +++ b/codegen/data_test.go @@ -3,10 +3,10 @@ package codegen import ( "testing" - "github.com/99designs/gqlgen/codegen/config" + "github.com/stretchr/testify/assert" "github.com/vektah/gqlparser/v2/ast" - "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/codegen/config" ) func TestData_Directives(t *testing.T) { diff --git a/codegen/directive.go b/codegen/directive.go index 973061129a..f955665be8 100644 --- a/codegen/directive.go +++ b/codegen/directive.go @@ -5,8 +5,9 @@ import ( "strconv" "strings" - "github.com/99designs/gqlgen/codegen/templates" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/codegen/templates" ) type DirectiveList map[string]*Directive diff --git a/codegen/field.go b/codegen/field.go index a7e1fb2ba6..6d11538a02 100644 --- a/codegen/field.go +++ b/codegen/field.go @@ -10,11 +10,12 @@ import ( "strconv" "strings" - "github.com/99designs/gqlgen/codegen/config" - "github.com/99designs/gqlgen/codegen/templates" "github.com/vektah/gqlparser/v2/ast" "golang.org/x/text/cases" "golang.org/x/text/language" + + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/codegen/templates" ) type Field struct { diff --git a/codegen/field_test.go b/codegen/field_test.go index 642d2d3f5c..0d5eb16216 100644 --- a/codegen/field_test.go +++ b/codegen/field_test.go @@ -8,9 +8,10 @@ import ( "go/types" "testing" - "github.com/99designs/gqlgen/codegen/config" "github.com/stretchr/testify/require" ast2 "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/codegen/config" ) func TestFindField(t *testing.T) { diff --git a/codegen/generate.go b/codegen/generate.go index 1ce8c329dc..d63758abf1 100644 --- a/codegen/generate.go +++ b/codegen/generate.go @@ -9,9 +9,10 @@ import ( "runtime" "strings" + "github.com/vektah/gqlparser/v2/ast" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" - "github.com/vektah/gqlparser/v2/ast" ) //go:embed *.gotpl diff --git a/codegen/object.go b/codegen/object.go index 8609232719..7164560e10 100644 --- a/codegen/object.go +++ b/codegen/object.go @@ -7,10 +7,11 @@ import ( "strings" "unicode" - "github.com/99designs/gqlgen/codegen/config" "github.com/vektah/gqlparser/v2/ast" "golang.org/x/text/cases" "golang.org/x/text/language" + + "github.com/99designs/gqlgen/codegen/config" ) type GoFieldType int diff --git a/codegen/templates/import_test.go b/codegen/templates/import_test.go index 483fd5ece8..d709f72cc9 100644 --- a/codegen/templates/import_test.go +++ b/codegen/templates/import_test.go @@ -6,9 +6,9 @@ import ( "os" "testing" - "github.com/99designs/gqlgen/internal/code" - "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/internal/code" ) func TestImports(t *testing.T) { diff --git a/codegen/templates/templates_test.go b/codegen/templates/templates_test.go index 12ccbb23c1..277a979cdb 100644 --- a/codegen/templates/templates_test.go +++ b/codegen/templates/templates_test.go @@ -7,10 +7,10 @@ import ( "path/filepath" "testing" - "github.com/99designs/gqlgen/internal/code" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/internal/code" ) //go:embed *.gotpl diff --git a/codegen/testserver/followschema/complexity_test.go b/codegen/testserver/followschema/complexity_test.go index 6a91e0f000..fd69a79c5e 100644 --- a/codegen/testserver/followschema/complexity_test.go +++ b/codegen/testserver/followschema/complexity_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/extension" - "github.com/stretchr/testify/require" ) func TestComplexityCollisions(t *testing.T) { diff --git a/codegen/testserver/followschema/defaults_test.go b/codegen/testserver/followschema/defaults_test.go index e5708a72e3..26adaa1373 100644 --- a/codegen/testserver/followschema/defaults_test.go +++ b/codegen/testserver/followschema/defaults_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func assertDefaults(t *testing.T, ret *DefaultParametersMirror) { diff --git a/codegen/testserver/followschema/directive_test.go b/codegen/testserver/followschema/directive_test.go index e995b2721c..b6d84d6932 100644 --- a/codegen/testserver/followschema/directive_test.go +++ b/codegen/testserver/followschema/directive_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type ckey string diff --git a/codegen/testserver/followschema/embedded_test.go b/codegen/testserver/followschema/embedded_test.go index b5e1575bac..207ea88182 100644 --- a/codegen/testserver/followschema/embedded_test.go +++ b/codegen/testserver/followschema/embedded_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type fakeUnexportedEmbeddedInterface struct{} diff --git a/codegen/testserver/followschema/enums_test.go b/codegen/testserver/followschema/enums_test.go index e7c80c29d2..c72293f169 100644 --- a/codegen/testserver/followschema/enums_test.go +++ b/codegen/testserver/followschema/enums_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestEnumsResolver(t *testing.T) { diff --git a/codegen/testserver/followschema/fields_order_test.go b/codegen/testserver/followschema/fields_order_test.go index d521c8fc99..2be70d9da5 100644 --- a/codegen/testserver/followschema/fields_order_test.go +++ b/codegen/testserver/followschema/fields_order_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type FieldsOrderPayloadResults struct { diff --git a/codegen/testserver/followschema/generated_test.go b/codegen/testserver/followschema/generated_test.go index 9d10cde2c3..1792b0b4e4 100644 --- a/codegen/testserver/followschema/generated_test.go +++ b/codegen/testserver/followschema/generated_test.go @@ -8,9 +8,10 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestForcedResolverFieldIsPointer(t *testing.T) { diff --git a/codegen/testserver/followschema/input_test.go b/codegen/testserver/followschema/input_test.go index 9a13f2d17f..27f6ada77a 100644 --- a/codegen/testserver/followschema/input_test.go +++ b/codegen/testserver/followschema/input_test.go @@ -6,9 +6,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestInput(t *testing.T) { diff --git a/codegen/testserver/followschema/interfaces_test.go b/codegen/testserver/followschema/interfaces_test.go index 3a7820fe52..2ef7312841 100644 --- a/codegen/testserver/followschema/interfaces_test.go +++ b/codegen/testserver/followschema/interfaces_test.go @@ -6,10 +6,11 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestInterfaces(t *testing.T) { diff --git a/codegen/testserver/followschema/introspection_test.go b/codegen/testserver/followschema/introspection_test.go index ef2bfafb53..2f3fbc30cb 100644 --- a/codegen/testserver/followschema/introspection_test.go +++ b/codegen/testserver/followschema/introspection_test.go @@ -4,12 +4,13 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/introspection" - "github.com/stretchr/testify/require" ) func TestIntrospection(t *testing.T) { diff --git a/codegen/testserver/followschema/maps_test.go b/codegen/testserver/followschema/maps_test.go index fe9750450f..314dc6055d 100644 --- a/codegen/testserver/followschema/maps_test.go +++ b/codegen/testserver/followschema/maps_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestMaps(t *testing.T) { diff --git a/codegen/testserver/followschema/middleware_test.go b/codegen/testserver/followschema/middleware_test.go index 16fe10e612..3d214dc05b 100644 --- a/codegen/testserver/followschema/middleware_test.go +++ b/codegen/testserver/followschema/middleware_test.go @@ -5,12 +5,12 @@ import ( "sync" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestMiddleware(t *testing.T) { diff --git a/codegen/testserver/followschema/modelmethod_test.go b/codegen/testserver/followschema/modelmethod_test.go index 4cf1803729..3fda4b2a39 100644 --- a/codegen/testserver/followschema/modelmethod_test.go +++ b/codegen/testserver/followschema/modelmethod_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestModelMethods(t *testing.T) { diff --git a/codegen/testserver/followschema/mutation_with_custom_scalar_test.go b/codegen/testserver/followschema/mutation_with_custom_scalar_test.go index 2f46c3ad4d..67f14ef31a 100644 --- a/codegen/testserver/followschema/mutation_with_custom_scalar_test.go +++ b/codegen/testserver/followschema/mutation_with_custom_scalar_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestErrorInsideMutationArgument(t *testing.T) { diff --git a/codegen/testserver/followschema/nulls_test.go b/codegen/testserver/followschema/nulls_test.go index 6049a7ca6e..e738ffecf5 100644 --- a/codegen/testserver/followschema/nulls_test.go +++ b/codegen/testserver/followschema/nulls_test.go @@ -5,9 +5,10 @@ import ( "errors" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestNullBubbling(t *testing.T) { diff --git a/codegen/testserver/followschema/panics_test.go b/codegen/testserver/followschema/panics_test.go index 4433aad01a..e22fc144b1 100644 --- a/codegen/testserver/followschema/panics_test.go +++ b/codegen/testserver/followschema/panics_test.go @@ -5,12 +5,12 @@ import ( "fmt" "testing" - "github.com/99designs/gqlgen/graphql" + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/v2/gqlerror" "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" - "github.com/vektah/gqlparser/v2/gqlerror" ) func TestPanics(t *testing.T) { diff --git a/codegen/testserver/followschema/primitive_objects_test.go b/codegen/testserver/followschema/primitive_objects_test.go index 87de88bb45..106518cacc 100644 --- a/codegen/testserver/followschema/primitive_objects_test.go +++ b/codegen/testserver/followschema/primitive_objects_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/assert" ) func TestPrimitiveObjects(t *testing.T) { diff --git a/codegen/testserver/followschema/ptr_to_any_test.go b/codegen/testserver/followschema/ptr_to_any_test.go index c1e78b8d80..3af48a89ed 100644 --- a/codegen/testserver/followschema/ptr_to_any_test.go +++ b/codegen/testserver/followschema/ptr_to_any_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestPtrToAny(t *testing.T) { diff --git a/codegen/testserver/followschema/ptr_to_ptr_input_test.go b/codegen/testserver/followschema/ptr_to_ptr_input_test.go index ab40d1d68d..785b3bceb7 100644 --- a/codegen/testserver/followschema/ptr_to_ptr_input_test.go +++ b/codegen/testserver/followschema/ptr_to_ptr_input_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type UpdatePtrToPtrResults struct { diff --git a/codegen/testserver/followschema/ptr_to_slice_test.go b/codegen/testserver/followschema/ptr_to_slice_test.go index 20818cc4d1..a95b6b46c9 100644 --- a/codegen/testserver/followschema/ptr_to_slice_test.go +++ b/codegen/testserver/followschema/ptr_to_slice_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestPtrToSlice(t *testing.T) { diff --git a/codegen/testserver/followschema/response_extension_test.go b/codegen/testserver/followschema/response_extension_test.go index 4ee1b5749f..92d1ade4af 100644 --- a/codegen/testserver/followschema/response_extension_test.go +++ b/codegen/testserver/followschema/response_extension_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestResponseExtension(t *testing.T) { diff --git a/codegen/testserver/followschema/scalar_context_test.go b/codegen/testserver/followschema/scalar_context_test.go index 2e2a0dc361..2d4bf1c8ba 100644 --- a/codegen/testserver/followschema/scalar_context_test.go +++ b/codegen/testserver/followschema/scalar_context_test.go @@ -5,9 +5,10 @@ import ( "math" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestFloatInfAndNaN(t *testing.T) { diff --git a/codegen/testserver/followschema/scalar_default_test.go b/codegen/testserver/followschema/scalar_default_test.go index f6fc05cb09..f0faa0139e 100644 --- a/codegen/testserver/followschema/scalar_default_test.go +++ b/codegen/testserver/followschema/scalar_default_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestDefaultScalarImplementation(t *testing.T) { diff --git a/codegen/testserver/followschema/slices_test.go b/codegen/testserver/followschema/slices_test.go index 19df15816b..de29686186 100644 --- a/codegen/testserver/followschema/slices_test.go +++ b/codegen/testserver/followschema/slices_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestSlices(t *testing.T) { diff --git a/codegen/testserver/followschema/subscription_test.go b/codegen/testserver/followschema/subscription_test.go index c449045190..b25fb53bd6 100644 --- a/codegen/testserver/followschema/subscription_test.go +++ b/codegen/testserver/followschema/subscription_test.go @@ -8,12 +8,12 @@ import ( "testing" "time" - "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/stretchr/testify/require" "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/graphql/handler/transport" ) func TestSubscriptions(t *testing.T) { diff --git a/codegen/testserver/followschema/time_test.go b/codegen/testserver/followschema/time_test.go index 60a098750a..947c1cc293 100644 --- a/codegen/testserver/followschema/time_test.go +++ b/codegen/testserver/followschema/time_test.go @@ -5,9 +5,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestTime(t *testing.T) { diff --git a/codegen/testserver/followschema/typefallback_test.go b/codegen/testserver/followschema/typefallback_test.go index 764661f84b..013ac1b7f8 100644 --- a/codegen/testserver/followschema/typefallback_test.go +++ b/codegen/testserver/followschema/typefallback_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestTypeFallback(t *testing.T) { diff --git a/codegen/testserver/followschema/validtypes_test.go b/codegen/testserver/followschema/validtypes_test.go index 2c0e67942a..026ebe029c 100644 --- a/codegen/testserver/followschema/validtypes_test.go +++ b/codegen/testserver/followschema/validtypes_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestValidType(t *testing.T) { diff --git a/codegen/testserver/followschema/wrapped_type_test.go b/codegen/testserver/followschema/wrapped_type_test.go index 95280b3d95..d28db51c3d 100644 --- a/codegen/testserver/followschema/wrapped_type_test.go +++ b/codegen/testserver/followschema/wrapped_type_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/codegen/testserver/followschema/otherpkg" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestWrappedTypes(t *testing.T) { diff --git a/codegen/testserver/singlefile/complexity_test.go b/codegen/testserver/singlefile/complexity_test.go index ac8e05a8c3..4dfbdffe7d 100644 --- a/codegen/testserver/singlefile/complexity_test.go +++ b/codegen/testserver/singlefile/complexity_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/extension" - "github.com/stretchr/testify/require" ) func TestComplexityCollisions(t *testing.T) { diff --git a/codegen/testserver/singlefile/defaults_test.go b/codegen/testserver/singlefile/defaults_test.go index 4b403ad151..f69efcf49a 100644 --- a/codegen/testserver/singlefile/defaults_test.go +++ b/codegen/testserver/singlefile/defaults_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func assertDefaults(t *testing.T, ret *DefaultParametersMirror) { diff --git a/codegen/testserver/singlefile/defer_test.go b/codegen/testserver/singlefile/defer_test.go index 876123401f..a5a1628da1 100644 --- a/codegen/testserver/singlefile/defer_test.go +++ b/codegen/testserver/singlefile/defer_test.go @@ -9,11 +9,12 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestDefer(t *testing.T) { diff --git a/codegen/testserver/singlefile/directive_test.go b/codegen/testserver/singlefile/directive_test.go index 0b7cb97df8..e5df58d2e5 100644 --- a/codegen/testserver/singlefile/directive_test.go +++ b/codegen/testserver/singlefile/directive_test.go @@ -5,10 +5,11 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type ckey string diff --git a/codegen/testserver/singlefile/embedded_test.go b/codegen/testserver/singlefile/embedded_test.go index dd9ededd14..d3dc9a1a71 100644 --- a/codegen/testserver/singlefile/embedded_test.go +++ b/codegen/testserver/singlefile/embedded_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type fakeUnexportedEmbeddedInterface struct{} diff --git a/codegen/testserver/singlefile/enums_test.go b/codegen/testserver/singlefile/enums_test.go index 11ac0d1fbf..9a12bd3fb5 100644 --- a/codegen/testserver/singlefile/enums_test.go +++ b/codegen/testserver/singlefile/enums_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestEnumsResolver(t *testing.T) { diff --git a/codegen/testserver/singlefile/fields_order_test.go b/codegen/testserver/singlefile/fields_order_test.go index eac294187f..daff5b6a38 100644 --- a/codegen/testserver/singlefile/fields_order_test.go +++ b/codegen/testserver/singlefile/fields_order_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type FieldsOrderPayloadResults struct { diff --git a/codegen/testserver/singlefile/generated_test.go b/codegen/testserver/singlefile/generated_test.go index 6d1dfa7e3c..63a6a4f2a1 100644 --- a/codegen/testserver/singlefile/generated_test.go +++ b/codegen/testserver/singlefile/generated_test.go @@ -8,9 +8,10 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestForcedResolverFieldIsPointer(t *testing.T) { diff --git a/codegen/testserver/singlefile/input_test.go b/codegen/testserver/singlefile/input_test.go index d33081b26c..ea05b2edfb 100644 --- a/codegen/testserver/singlefile/input_test.go +++ b/codegen/testserver/singlefile/input_test.go @@ -6,9 +6,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestInput(t *testing.T) { diff --git a/codegen/testserver/singlefile/interfaces_test.go b/codegen/testserver/singlefile/interfaces_test.go index 23b3fb0206..9a38a3f942 100644 --- a/codegen/testserver/singlefile/interfaces_test.go +++ b/codegen/testserver/singlefile/interfaces_test.go @@ -6,10 +6,11 @@ import ( "reflect" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestInterfaces(t *testing.T) { diff --git a/codegen/testserver/singlefile/introspection_test.go b/codegen/testserver/singlefile/introspection_test.go index f78a8202c1..64958e7e79 100644 --- a/codegen/testserver/singlefile/introspection_test.go +++ b/codegen/testserver/singlefile/introspection_test.go @@ -4,12 +4,13 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/introspection" - "github.com/stretchr/testify/require" ) func TestIntrospection(t *testing.T) { diff --git a/codegen/testserver/singlefile/maps_test.go b/codegen/testserver/singlefile/maps_test.go index 0c7129ae61..1c9cbb465f 100644 --- a/codegen/testserver/singlefile/maps_test.go +++ b/codegen/testserver/singlefile/maps_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestMaps(t *testing.T) { diff --git a/codegen/testserver/singlefile/middleware_test.go b/codegen/testserver/singlefile/middleware_test.go index 5a840d0751..7b404d41ea 100644 --- a/codegen/testserver/singlefile/middleware_test.go +++ b/codegen/testserver/singlefile/middleware_test.go @@ -5,12 +5,12 @@ import ( "sync" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestMiddleware(t *testing.T) { diff --git a/codegen/testserver/singlefile/modelmethod_test.go b/codegen/testserver/singlefile/modelmethod_test.go index aefb14aa7b..a584b35b78 100644 --- a/codegen/testserver/singlefile/modelmethod_test.go +++ b/codegen/testserver/singlefile/modelmethod_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestModelMethods(t *testing.T) { diff --git a/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go b/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go index 3290b373e2..5237e99f2f 100644 --- a/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go +++ b/codegen/testserver/singlefile/mutation_with_custom_scalar_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestErrorInsideMutationArgument(t *testing.T) { diff --git a/codegen/testserver/singlefile/nulls_test.go b/codegen/testserver/singlefile/nulls_test.go index 853428f485..c2609676fc 100644 --- a/codegen/testserver/singlefile/nulls_test.go +++ b/codegen/testserver/singlefile/nulls_test.go @@ -5,9 +5,10 @@ import ( "errors" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestNullBubbling(t *testing.T) { diff --git a/codegen/testserver/singlefile/panics_test.go b/codegen/testserver/singlefile/panics_test.go index 209344d79d..a426130618 100644 --- a/codegen/testserver/singlefile/panics_test.go +++ b/codegen/testserver/singlefile/panics_test.go @@ -5,12 +5,12 @@ import ( "fmt" "testing" - "github.com/99designs/gqlgen/graphql" + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/v2/gqlerror" "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" - "github.com/vektah/gqlparser/v2/gqlerror" ) func TestPanics(t *testing.T) { diff --git a/codegen/testserver/singlefile/primitive_objects_test.go b/codegen/testserver/singlefile/primitive_objects_test.go index 80e7a96d7a..c16e305565 100644 --- a/codegen/testserver/singlefile/primitive_objects_test.go +++ b/codegen/testserver/singlefile/primitive_objects_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/assert" ) func TestPrimitiveObjects(t *testing.T) { diff --git a/codegen/testserver/singlefile/ptr_to_any_test.go b/codegen/testserver/singlefile/ptr_to_any_test.go index 88feadecc7..7ad1dcb408 100644 --- a/codegen/testserver/singlefile/ptr_to_any_test.go +++ b/codegen/testserver/singlefile/ptr_to_any_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestPtrToAny(t *testing.T) { diff --git a/codegen/testserver/singlefile/ptr_to_ptr_input_test.go b/codegen/testserver/singlefile/ptr_to_ptr_input_test.go index 1e46e7e33c..f5f1f381bd 100644 --- a/codegen/testserver/singlefile/ptr_to_ptr_input_test.go +++ b/codegen/testserver/singlefile/ptr_to_ptr_input_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) type UpdatePtrToPtrResults struct { diff --git a/codegen/testserver/singlefile/ptr_to_slice_test.go b/codegen/testserver/singlefile/ptr_to_slice_test.go index 0eee0bb873..5549ec68ab 100644 --- a/codegen/testserver/singlefile/ptr_to_slice_test.go +++ b/codegen/testserver/singlefile/ptr_to_slice_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestPtrToSlice(t *testing.T) { diff --git a/codegen/testserver/singlefile/response_extension_test.go b/codegen/testserver/singlefile/response_extension_test.go index 9e570dbda0..8fca678027 100644 --- a/codegen/testserver/singlefile/response_extension_test.go +++ b/codegen/testserver/singlefile/response_extension_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestResponseExtension(t *testing.T) { diff --git a/codegen/testserver/singlefile/scalar_context_test.go b/codegen/testserver/singlefile/scalar_context_test.go index 2070b0996b..63d2ad32fb 100644 --- a/codegen/testserver/singlefile/scalar_context_test.go +++ b/codegen/testserver/singlefile/scalar_context_test.go @@ -5,9 +5,10 @@ import ( "math" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestFloatInfAndNaN(t *testing.T) { diff --git a/codegen/testserver/singlefile/scalar_default_test.go b/codegen/testserver/singlefile/scalar_default_test.go index 556a3eccb4..f23f6c2e82 100644 --- a/codegen/testserver/singlefile/scalar_default_test.go +++ b/codegen/testserver/singlefile/scalar_default_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestDefaultScalarImplementation(t *testing.T) { diff --git a/codegen/testserver/singlefile/slices_test.go b/codegen/testserver/singlefile/slices_test.go index b6c3e37b9a..596e332528 100644 --- a/codegen/testserver/singlefile/slices_test.go +++ b/codegen/testserver/singlefile/slices_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestSlices(t *testing.T) { diff --git a/codegen/testserver/singlefile/subscription_test.go b/codegen/testserver/singlefile/subscription_test.go index 567b5acd03..6199bab6d5 100644 --- a/codegen/testserver/singlefile/subscription_test.go +++ b/codegen/testserver/singlefile/subscription_test.go @@ -8,12 +8,12 @@ import ( "testing" "time" - "github.com/99designs/gqlgen/graphql/handler/transport" + "github.com/stretchr/testify/require" "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/graphql/handler/transport" ) func TestSubscriptions(t *testing.T) { diff --git a/codegen/testserver/singlefile/time_test.go b/codegen/testserver/singlefile/time_test.go index 90c8a0c539..1a7c9f9ac3 100644 --- a/codegen/testserver/singlefile/time_test.go +++ b/codegen/testserver/singlefile/time_test.go @@ -5,9 +5,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestTime(t *testing.T) { diff --git a/codegen/testserver/singlefile/typefallback_test.go b/codegen/testserver/singlefile/typefallback_test.go index 13ba74449c..55f49282ed 100644 --- a/codegen/testserver/singlefile/typefallback_test.go +++ b/codegen/testserver/singlefile/typefallback_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestTypeFallback(t *testing.T) { diff --git a/codegen/testserver/singlefile/validtypes_test.go b/codegen/testserver/singlefile/validtypes_test.go index 28c5f07974..6b27a4a399 100644 --- a/codegen/testserver/singlefile/validtypes_test.go +++ b/codegen/testserver/singlefile/validtypes_test.go @@ -4,9 +4,10 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestValidType(t *testing.T) { diff --git a/codegen/testserver/singlefile/wrapped_type_test.go b/codegen/testserver/singlefile/wrapped_type_test.go index 13a9ccab84..98ffaa3a7c 100644 --- a/codegen/testserver/singlefile/wrapped_type_test.go +++ b/codegen/testserver/singlefile/wrapped_type_test.go @@ -4,10 +4,11 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/codegen/testserver/singlefile/otherpkg" "github.com/99designs/gqlgen/graphql/handler" - "github.com/stretchr/testify/require" ) func TestWrappedTypes(t *testing.T) { diff --git a/complexity/complexity.go b/complexity/complexity.go index e3ecf7612d..aa0f86432e 100644 --- a/complexity/complexity.go +++ b/complexity/complexity.go @@ -1,8 +1,9 @@ package complexity import ( - "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" ) func Calculate(es graphql.ExecutableSchema, op *ast.OperationDefinition, vars map[string]interface{}) int { diff --git a/complexity/complexity_test.go b/complexity/complexity_test.go index 0c4be24e1c..e99acf0efb 100644 --- a/complexity/complexity_test.go +++ b/complexity/complexity_test.go @@ -4,10 +4,11 @@ import ( "math" "testing" - "github.com/99designs/gqlgen/graphql" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" ) var schema = gqlparser.MustLoadSchema( diff --git a/docs/content/reference/scalars.md b/docs/content/reference/scalars.md index abec39910c..137d3db8f6 100644 --- a/docs/content/reference/scalars.md +++ b/docs/content/reference/scalars.md @@ -71,6 +71,23 @@ scalar Any Maps an arbitrary GraphQL value to a `interface{}` Go type. +### Duration + +```graphql +scalar Duration +``` +This maps a `Duration` scalar value conforming to the `ISO8601` standard (ex.: `P1Y2D`) to a `time.Duration` type. + +If you add to gqlgen.yml: +```yaml +models: + Duration: + model: + - github.com/99designs/gqlgen/graphql.Duration +``` + +And then add `scalar Duration` to `schema.graphql` + ## Custom scalars with user defined types For user defined types you can implement the [graphql.Marshaler](https://pkg.go.dev/github.com/99designs/gqlgen/graphql#Marshaler) and [graphql.Unmarshaler](https://pkg.go.dev/github.com/99designs/gqlgen/graphql#Unmarshaler) or implement the [graphql.ContextMarshaler](https://pkg.go.dev/github.com/99designs/gqlgen/graphql#ContextMarshaler) and [graphql.ContextUnmarshaler](https://pkg.go.dev/github.com/99designs/gqlgen/graphql#ContextUnmarshaler) interfaces and they will be called. diff --git a/go.mod b/go.mod index f856dac1cf..b2bbd184b1 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/mattn/go-colorable v0.1.13 github.com/mattn/go-isatty v0.0.19 github.com/mitchellh/mapstructure v1.5.0 + github.com/sosodev/duration v1.1.0 github.com/stretchr/testify v1.8.2 github.com/urfave/cli/v2 v2.25.5 github.com/vektah/gqlparser/v2 v2.5.10 diff --git a/go.sum b/go.sum index 85c8dff9fd..46bd6ffb74 100644 --- a/go.sum +++ b/go.sum @@ -37,6 +37,8 @@ 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.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sosodev/duration v1.1.0 h1:kQcaiGbJaIsRqgQy7VGlZrVw1giWO+lDoX3MCPnpVO4= +github.com/sosodev/duration v1.1.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg= 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= diff --git a/graphql/duration.go b/graphql/duration.go new file mode 100644 index 0000000000..3eb392db87 --- /dev/null +++ b/graphql/duration.go @@ -0,0 +1,27 @@ +package graphql + +import ( + "fmt" + "time" + + dur "github.com/sosodev/duration" +) + +// UnmarshalDuration returns the duration from a string in ISO8601 format +func UnmarshalDuration(v interface{}) (time.Duration, error) { + input, ok := v.(string) + if !ok { + return 0, fmt.Errorf("input must be a string") + } + + d2, err := dur.Parse(input) + if err != nil { + return 0, err + } + return d2.ToTimeDuration(), nil +} + +// MarshalDuration returns the duration on ISO8601 format +func MarshalDuration(d time.Duration) Marshaler { + return MarshalString(dur.Format(d)) +} diff --git a/graphql/duration_test.go b/graphql/duration_test.go new file mode 100644 index 0000000000..56b6031f71 --- /dev/null +++ b/graphql/duration_test.go @@ -0,0 +1,26 @@ +package graphql + +import ( + "bytes" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestDurationMarshaling(t *testing.T) { + t.Run("UnmarshalDuration", func(t *testing.T) { + d, err := UnmarshalDuration("P2Y") + assert.NoError(t, err) + + assert.Equal(t, float64(365*24*2), d.Hours()) + }) + t.Run("MarshalDuration", func(t *testing.T) { + m := MarshalDuration(time.Hour * 365 * 24 * 2) + + buf := new(bytes.Buffer) + m.MarshalGQL(buf) + + assert.Equal(t, "\"P2Y\"", buf.String()) + }) +} diff --git a/graphql/executor/executor.go b/graphql/executor/executor.go index c46a007b99..ef0603eaa0 100644 --- a/graphql/executor/executor.go +++ b/graphql/executor/executor.go @@ -3,12 +3,13 @@ package executor import ( "context" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/errcode" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/parser" "github.com/vektah/gqlparser/v2/validator" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" ) // Executor executes graphql queries against a schema. diff --git a/graphql/executor/executor_test.go b/graphql/executor/executor_test.go index cf1944bd9d..79530c1fc7 100644 --- a/graphql/executor/executor_test.go +++ b/graphql/executor/executor_test.go @@ -4,14 +4,15 @@ import ( "context" "testing" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/errcode" - "github.com/99designs/gqlgen/graphql/executor/testexecutor" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/parser" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" + "github.com/99designs/gqlgen/graphql/executor/testexecutor" ) func TestExecutor(t *testing.T) { diff --git a/graphql/executor/testexecutor/testexecutor.go b/graphql/executor/testexecutor/testexecutor.go index bf8fd9850f..a3e0a300dc 100644 --- a/graphql/executor/testexecutor/testexecutor.go +++ b/graphql/executor/testexecutor/testexecutor.go @@ -8,10 +8,11 @@ import ( "io" "time" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/executor" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/executor" ) type MockResponse struct { diff --git a/graphql/handler/apollofederatedtracingv1/tracing.go b/graphql/handler/apollofederatedtracingv1/tracing.go index b186201beb..1c969b4f64 100644 --- a/graphql/handler/apollofederatedtracingv1/tracing.go +++ b/graphql/handler/apollofederatedtracingv1/tracing.go @@ -5,8 +5,9 @@ import ( "encoding/base64" "fmt" - "github.com/99designs/gqlgen/graphql" "google.golang.org/protobuf/proto" + + "github.com/99designs/gqlgen/graphql" ) type ( diff --git a/graphql/handler/apollofederatedtracingv1/tracing_test.go b/graphql/handler/apollofederatedtracingv1/tracing_test.go index 7217217ed6..aa05de7127 100644 --- a/graphql/handler/apollofederatedtracingv1/tracing_test.go +++ b/graphql/handler/apollofederatedtracingv1/tracing_test.go @@ -12,6 +12,11 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/v2/gqlerror" + "google.golang.org/protobuf/proto" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler/apollofederatedtracingv1" "github.com/99designs/gqlgen/graphql/handler/apollofederatedtracingv1/generated" @@ -19,10 +24,6 @@ import ( "github.com/99designs/gqlgen/graphql/handler/lru" "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/vektah/gqlparser/v2/gqlerror" - "google.golang.org/protobuf/proto" ) type alwaysError struct{} diff --git a/graphql/handler/apollofederatedtracingv1/tree_builder.go b/graphql/handler/apollofederatedtracingv1/tree_builder.go index a54b12db58..e211e626c0 100644 --- a/graphql/handler/apollofederatedtracingv1/tree_builder.go +++ b/graphql/handler/apollofederatedtracingv1/tree_builder.go @@ -6,9 +6,10 @@ import ( "sync" "time" + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler/apollofederatedtracingv1/generated" - "google.golang.org/protobuf/types/known/timestamppb" ) type TreeBuilder struct { diff --git a/graphql/handler/apollotracing/tracer.go b/graphql/handler/apollotracing/tracer.go index d1e92bbfdc..0d5fc597c0 100644 --- a/graphql/handler/apollotracing/tracer.go +++ b/graphql/handler/apollotracing/tracer.go @@ -5,8 +5,9 @@ import ( "sync" "time" - "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" ) type ( diff --git a/graphql/handler/apollotracing/tracer_test.go b/graphql/handler/apollotracing/tracer_test.go index 789448cae9..74e4e6e127 100644 --- a/graphql/handler/apollotracing/tracer_test.go +++ b/graphql/handler/apollotracing/tracer_test.go @@ -9,16 +9,17 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler/apollotracing" "github.com/99designs/gqlgen/graphql/handler/extension" "github.com/99designs/gqlgen/graphql/handler/lru" "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/vektah/gqlparser/v2/ast" - "github.com/vektah/gqlparser/v2/gqlerror" ) type alwaysError struct{} diff --git a/graphql/handler/extension/apq.go b/graphql/handler/extension/apq.go index 866276eed9..465c2ada61 100644 --- a/graphql/handler/extension/apq.go +++ b/graphql/handler/extension/apq.go @@ -6,12 +6,11 @@ import ( "encoding/hex" "fmt" - "github.com/99designs/gqlgen/graphql/errcode" - + "github.com/mitchellh/mapstructure" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/99designs/gqlgen/graphql" - "github.com/mitchellh/mapstructure" + "github.com/99designs/gqlgen/graphql/errcode" ) const ( diff --git a/graphql/handler/extension/apq_test.go b/graphql/handler/extension/apq_test.go index 66970c62e9..92b06a5133 100644 --- a/graphql/handler/extension/apq_test.go +++ b/graphql/handler/extension/apq_test.go @@ -5,11 +5,12 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler/extension" "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/require" ) func TestAPQIntegration(t *testing.T) { diff --git a/graphql/handler/extension/complexity.go b/graphql/handler/extension/complexity.go index e88848d18c..a5b6a60409 100644 --- a/graphql/handler/extension/complexity.go +++ b/graphql/handler/extension/complexity.go @@ -4,10 +4,11 @@ import ( "context" "fmt" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/99designs/gqlgen/complexity" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/errcode" - "github.com/vektah/gqlparser/v2/gqlerror" ) const errComplexityLimit = "COMPLEXITY_LIMIT_EXCEEDED" diff --git a/graphql/handler/extension/complexity_test.go b/graphql/handler/extension/complexity_test.go index e533403e1a..5141f43ee4 100644 --- a/graphql/handler/extension/complexity_test.go +++ b/graphql/handler/extension/complexity_test.go @@ -7,11 +7,12 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler/extension" "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/require" ) func TestHandlerComplexity(t *testing.T) { diff --git a/graphql/handler/extension/introspection.go b/graphql/handler/extension/introspection.go index acc5db2fbc..8e3912651d 100644 --- a/graphql/handler/extension/introspection.go +++ b/graphql/handler/extension/introspection.go @@ -3,8 +3,9 @@ package extension import ( "context" - "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/gqlerror" + + "github.com/99designs/gqlgen/graphql" ) // EnableIntrospection enables clients to reflect all of the types available on the graph. diff --git a/graphql/handler/extension/introspection_test.go b/graphql/handler/extension/introspection_test.go index e001eb529f..f719c262a6 100644 --- a/graphql/handler/extension/introspection_test.go +++ b/graphql/handler/extension/introspection_test.go @@ -4,8 +4,9 @@ import ( "context" "testing" - "github.com/99designs/gqlgen/graphql" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/graphql" ) func TestIntrospection(t *testing.T) { diff --git a/graphql/handler/lru/lru.go b/graphql/handler/lru/lru.go index 68241ababf..6ae8a38e64 100644 --- a/graphql/handler/lru/lru.go +++ b/graphql/handler/lru/lru.go @@ -3,8 +3,9 @@ package lru import ( "context" - "github.com/99designs/gqlgen/graphql" lru "github.com/hashicorp/golang-lru/v2" + + "github.com/99designs/gqlgen/graphql" ) type LRU struct { diff --git a/graphql/handler/server.go b/graphql/handler/server.go index b6524d8da1..fd365ccbbf 100644 --- a/graphql/handler/server.go +++ b/graphql/handler/server.go @@ -7,12 +7,13 @@ import ( "net/http" "time" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/executor" "github.com/99designs/gqlgen/graphql/handler/extension" "github.com/99designs/gqlgen/graphql/handler/lru" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/vektah/gqlparser/v2/gqlerror" ) type ( diff --git a/graphql/handler/server_test.go b/graphql/handler/server_test.go index b1ac60fb49..4b31c09ac4 100644 --- a/graphql/handler/server_test.go +++ b/graphql/handler/server_test.go @@ -8,14 +8,15 @@ import ( "net/url" "testing" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/handler/testserver" - "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" "github.com/vektah/gqlparser/v2/parser" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler/testserver" + "github.com/99designs/gqlgen/graphql/handler/transport" ) func TestServer(t *testing.T) { diff --git a/graphql/handler/testserver/testserver.go b/graphql/handler/testserver/testserver.go index 9556d6828a..85dc7d2899 100644 --- a/graphql/handler/testserver/testserver.go +++ b/graphql/handler/testserver/testserver.go @@ -5,10 +5,11 @@ import ( "fmt" "time" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/handler" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler" ) // New provides a server for use in tests that isn't relying on generated code. It isnt a perfect reproduction of diff --git a/graphql/handler/transport/error.go b/graphql/handler/transport/error.go index b1aeaf144d..18f09f5567 100644 --- a/graphql/handler/transport/error.go +++ b/graphql/handler/transport/error.go @@ -5,8 +5,9 @@ import ( "fmt" "net/http" - "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/gqlerror" + + "github.com/99designs/gqlgen/graphql" ) // SendError sends a best effort error to a raw response writer. It assumes the client can understand the standard diff --git a/graphql/handler/transport/headers_test.go b/graphql/handler/transport/headers_test.go index 4673522de7..93fa4bf6b6 100644 --- a/graphql/handler/transport/headers_test.go +++ b/graphql/handler/transport/headers_test.go @@ -6,14 +6,15 @@ import ( "net/http/httptest" "testing" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/handler" - "github.com/99designs/gqlgen/graphql/handler/testserver" - "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/testserver" + "github.com/99designs/gqlgen/graphql/handler/transport" ) func TestHeadersWithPOST(t *testing.T) { diff --git a/graphql/handler/transport/http_form_multipart_test.go b/graphql/handler/transport/http_form_multipart_test.go index 4eb636378b..6d7c327933 100644 --- a/graphql/handler/transport/http_form_multipart_test.go +++ b/graphql/handler/transport/http_form_multipart_test.go @@ -11,12 +11,13 @@ import ( "net/textproto" "testing" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/handler" - "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/transport" ) func TestFileUpload(t *testing.T) { diff --git a/graphql/handler/transport/http_form_urlencode_test.go b/graphql/handler/transport/http_form_urlencode_test.go index 8eecf449e1..fb984167a0 100644 --- a/graphql/handler/transport/http_form_urlencode_test.go +++ b/graphql/handler/transport/http_form_urlencode_test.go @@ -7,9 +7,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" ) func TestUrlEncodedForm(t *testing.T) { diff --git a/graphql/handler/transport/http_get.go b/graphql/handler/transport/http_get.go index 324fd98683..9a47bfbef8 100644 --- a/graphql/handler/transport/http_get.go +++ b/graphql/handler/transport/http_get.go @@ -7,10 +7,11 @@ import ( "net/url" "strings" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/errcode" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/gqlerror" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" ) // GET implements the GET side of the default HTTP transport diff --git a/graphql/handler/transport/http_get_test.go b/graphql/handler/transport/http_get_test.go index 5e46d23185..6e0dde07f5 100644 --- a/graphql/handler/transport/http_get_test.go +++ b/graphql/handler/transport/http_get_test.go @@ -4,9 +4,10 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" ) func TestGET(t *testing.T) { diff --git a/graphql/handler/transport/http_graphql_test.go b/graphql/handler/transport/http_graphql_test.go index e1add4a498..53fb891f00 100644 --- a/graphql/handler/transport/http_graphql_test.go +++ b/graphql/handler/transport/http_graphql_test.go @@ -7,9 +7,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" ) func TestGRAPHQL(t *testing.T) { diff --git a/graphql/handler/transport/http_post_test.go b/graphql/handler/transport/http_post_test.go index a26ba12912..a7ecd7d5eb 100644 --- a/graphql/handler/transport/http_post_test.go +++ b/graphql/handler/transport/http_post_test.go @@ -7,9 +7,10 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/99designs/gqlgen/graphql/handler/testserver" "github.com/99designs/gqlgen/graphql/handler/transport" - "github.com/stretchr/testify/assert" ) func TestPOST(t *testing.T) { diff --git a/graphql/handler/transport/util.go b/graphql/handler/transport/util.go index ce845c1964..19b7521c08 100644 --- a/graphql/handler/transport/util.go +++ b/graphql/handler/transport/util.go @@ -5,8 +5,9 @@ import ( "fmt" "io" - "github.com/99designs/gqlgen/graphql" "github.com/vektah/gqlparser/v2/gqlerror" + + "github.com/99designs/gqlgen/graphql" ) func writeJson(w io.Writer, response *graphql.Response) { diff --git a/graphql/handler/transport/websocket.go b/graphql/handler/transport/websocket.go index 1969f9e285..e1334b9290 100644 --- a/graphql/handler/transport/websocket.go +++ b/graphql/handler/transport/websocket.go @@ -12,10 +12,11 @@ import ( "sync" "time" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/errcode" "github.com/gorilla/websocket" "github.com/vektah/gqlparser/v2/gqlerror" + + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" ) type ( diff --git a/graphql/handler/transport/websocket_test.go b/graphql/handler/transport/websocket_test.go index f05a9df189..e933677248 100644 --- a/graphql/handler/transport/websocket_test.go +++ b/graphql/handler/transport/websocket_test.go @@ -10,16 +10,17 @@ import ( "testing" "time" - "github.com/99designs/gqlgen/client" - "github.com/99designs/gqlgen/graphql" - "github.com/99designs/gqlgen/graphql/handler" - "github.com/99designs/gqlgen/graphql/handler/testserver" - "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/gorilla/websocket" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" + + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/testserver" + "github.com/99designs/gqlgen/graphql/handler/transport" ) type ckey string diff --git a/handler/handler.go b/handler/handler.go index 19491020de..08e6a4c0e1 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -5,13 +5,14 @@ import ( "net/http" "time" + "github.com/gorilla/websocket" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/extension" "github.com/99designs/gqlgen/graphql/handler/lru" "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/playground" - "github.com/gorilla/websocket" ) // Deprecated: switch to graphql/handler.New diff --git a/integration/server/cmd/integration/server.go b/integration/server/cmd/integration/server.go index fec1c4827a..df542a4045 100644 --- a/integration/server/cmd/integration/server.go +++ b/integration/server/cmd/integration/server.go @@ -8,6 +8,8 @@ import ( "os" "time" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/graphql/handler/extension" @@ -15,7 +17,6 @@ import ( "github.com/99designs/gqlgen/graphql/handler/transport" "github.com/99designs/gqlgen/graphql/playground" "github.com/99designs/gqlgen/integration/server" - "github.com/vektah/gqlparser/v2/gqlerror" ) const defaultPort = "8080" diff --git a/internal/imports/prune.go b/internal/imports/prune.go index d42a415791..f5fc71c697 100644 --- a/internal/imports/prune.go +++ b/internal/imports/prune.go @@ -10,10 +10,10 @@ import ( "go/token" "strings" - "github.com/99designs/gqlgen/internal/code" - "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/imports" + + "github.com/99designs/gqlgen/internal/code" ) type visitFn func(node ast.Node) diff --git a/internal/imports/prune_test.go b/internal/imports/prune_test.go index 0006aec9ac..d312aff6bc 100644 --- a/internal/imports/prune_test.go +++ b/internal/imports/prune_test.go @@ -5,8 +5,9 @@ import ( "strings" "testing" - "github.com/99designs/gqlgen/internal/code" "github.com/stretchr/testify/require" + + "github.com/99designs/gqlgen/internal/code" ) func TestPrune(t *testing.T) { diff --git a/internal/imports/testdata/unused.expected.go b/internal/imports/testdata/unused.expected.go index 95cbe2d00f..f9d393d7ee 100644 --- a/internal/imports/testdata/unused.expected.go +++ b/internal/imports/testdata/unused.expected.go @@ -3,6 +3,7 @@ package testdata import ( a "fmt" "time" + _ "underscore" ) diff --git a/internal/imports/testdata/unused.go b/internal/imports/testdata/unused.go index 95cbe2d00f..f9d393d7ee 100644 --- a/internal/imports/testdata/unused.go +++ b/internal/imports/testdata/unused.go @@ -3,6 +3,7 @@ package testdata import ( a "fmt" "time" + _ "underscore" ) diff --git a/internal/rewrite/rewriter.go b/internal/rewrite/rewriter.go index 1ca722dcfd..7e68e55de9 100644 --- a/internal/rewrite/rewriter.go +++ b/internal/rewrite/rewriter.go @@ -10,8 +10,9 @@ import ( "strconv" "strings" - "github.com/99designs/gqlgen/internal/code" "golang.org/x/tools/go/packages" + + "github.com/99designs/gqlgen/internal/code" ) type Rewriter struct { diff --git a/internal/rewrite/rewriter_test.go b/internal/rewrite/rewriter_test.go index fae86668fb..9ac5ffb0e7 100644 --- a/internal/rewrite/rewriter_test.go +++ b/internal/rewrite/rewriter_test.go @@ -26,14 +26,14 @@ func TestRewriter(t *testing.T) { imps := r.ExistingImports("testdata/example.go") require.Len(t, imps, 2) assert.Equal(t, []Import{ - { - Alias: "", - ImportPath: "fmt", - }, { Alias: "lol", ImportPath: "bytes", }, + { + Alias: "", + ImportPath: "fmt", + }, }, imps) }) diff --git a/internal/rewrite/testdata/example.go b/internal/rewrite/testdata/example.go index 949bbe8235..6a3297ad2b 100644 --- a/internal/rewrite/testdata/example.go +++ b/internal/rewrite/testdata/example.go @@ -1,9 +1,8 @@ package testdata import ( - "fmt" - lol "bytes" + "fmt" ) type Foo struct { diff --git a/main.go b/main.go index af365bfeb9..e0420d1502 100644 --- a/main.go +++ b/main.go @@ -12,12 +12,13 @@ import ( "os" "path/filepath" + "github.com/urfave/cli/v2" + "github.com/99designs/gqlgen/api" "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/internal/code" "github.com/99designs/gqlgen/plugin/servergen" - "github.com/urfave/cli/v2" ) //go:embed init-templates/schema.graphqls diff --git a/plugin/federation/entity.go b/plugin/federation/entity.go index 04a3c033b0..042dd59ad7 100644 --- a/plugin/federation/entity.go +++ b/plugin/federation/entity.go @@ -3,10 +3,11 @@ package federation import ( "go/types" + "github.com/vektah/gqlparser/v2/ast" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" "github.com/99designs/gqlgen/plugin/federation/fieldset" - "github.com/vektah/gqlparser/v2/ast" ) // Entity represents a federated type diff --git a/plugin/federation/federation_entityresolver_test.go b/plugin/federation/federation_entityresolver_test.go index 4cbc160245..cd96c5d498 100644 --- a/plugin/federation/federation_entityresolver_test.go +++ b/plugin/federation/federation_entityresolver_test.go @@ -7,10 +7,10 @@ import ( "strings" "testing" - "github.com/99designs/gqlgen/client" - "github.com/99designs/gqlgen/graphql/handler" "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/client" + "github.com/99designs/gqlgen/graphql/handler" "github.com/99designs/gqlgen/plugin/federation/testdata/entityresolver" "github.com/99designs/gqlgen/plugin/federation/testdata/entityresolver/generated" ) diff --git a/plugin/federation/federation_test.go b/plugin/federation/federation_test.go index cc5b20ee3b..1458743174 100644 --- a/plugin/federation/federation_test.go +++ b/plugin/federation/federation_test.go @@ -3,9 +3,10 @@ package federation import ( "testing" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/codegen" "github.com/99designs/gqlgen/codegen/config" - "github.com/stretchr/testify/require" ) func TestWithEntities(t *testing.T) { diff --git a/plugin/federation/fieldset/fieldset.go b/plugin/federation/fieldset/fieldset.go index 059a3c8325..59e4775368 100644 --- a/plugin/federation/fieldset/fieldset.go +++ b/plugin/federation/fieldset/fieldset.go @@ -4,9 +4,10 @@ import ( "fmt" "strings" + "github.com/vektah/gqlparser/v2/ast" + "github.com/99designs/gqlgen/codegen" "github.com/99designs/gqlgen/codegen/templates" - "github.com/vektah/gqlparser/v2/ast" ) // Set represents a FieldSet that is used in federation directives @key and @requires. diff --git a/plugin/modelgen/models.go b/plugin/modelgen/models.go index 4383d76c92..798a936f57 100644 --- a/plugin/modelgen/models.go +++ b/plugin/modelgen/models.go @@ -9,10 +9,11 @@ import ( "strings" "text/template" + "github.com/vektah/gqlparser/v2/ast" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" "github.com/99designs/gqlgen/plugin" - "github.com/vektah/gqlparser/v2/ast" ) //go:embed models.gotpl diff --git a/plugin/modelgen/models_test.go b/plugin/modelgen/models_test.go index 8607615772..a9182d02f0 100644 --- a/plugin/modelgen/models_test.go +++ b/plugin/modelgen/models_test.go @@ -14,6 +14,9 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/plugin/modelgen/internal/extrafields" @@ -23,8 +26,6 @@ import ( "github.com/99designs/gqlgen/plugin/modelgen/out_enable_model_json_omitempty_tag_true" "github.com/99designs/gqlgen/plugin/modelgen/out_nullable_input_omittable" "github.com/99designs/gqlgen/plugin/modelgen/out_struct_pointers" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestModelGeneration(t *testing.T) { diff --git a/plugin/plugin.go b/plugin/plugin.go index 69801c8816..214c58d9e1 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -3,9 +3,10 @@ package plugin import ( + "github.com/vektah/gqlparser/v2/ast" + "github.com/99designs/gqlgen/codegen" "github.com/99designs/gqlgen/codegen/config" - "github.com/vektah/gqlparser/v2/ast" ) type Plugin interface { diff --git a/plugin/resolvergen/resolver_test.go b/plugin/resolvergen/resolver_test.go index 2cf9713f7c..17650e8f20 100644 --- a/plugin/resolvergen/resolver_test.go +++ b/plugin/resolvergen/resolver_test.go @@ -6,10 +6,11 @@ import ( "syscall" "testing" - "github.com/99designs/gqlgen/codegen" - "github.com/99designs/gqlgen/codegen/config" "github.com/stretchr/testify/require" "golang.org/x/tools/go/packages" + + "github.com/99designs/gqlgen/codegen" + "github.com/99designs/gqlgen/codegen/config" ) func TestLayoutSingleFile(t *testing.T) { diff --git a/plugin/stubgen/stubs.go b/plugin/stubgen/stubs.go index 01db65b1f9..8f1b81293c 100644 --- a/plugin/stubgen/stubs.go +++ b/plugin/stubgen/stubs.go @@ -5,11 +5,10 @@ import ( "path/filepath" "syscall" - "github.com/99designs/gqlgen/internal/code" - "github.com/99designs/gqlgen/codegen" "github.com/99designs/gqlgen/codegen/config" "github.com/99designs/gqlgen/codegen/templates" + "github.com/99designs/gqlgen/internal/code" "github.com/99designs/gqlgen/plugin" ) From 3ff523ba5f4564432f7c8c0631ccc3d25754a407 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 12:34:52 -0400 Subject: [PATCH 46/54] Bump postcss from 8.4.24 to 8.4.31 in /integration (#2819) Bumps [postcss](https://github.com/postcss/postcss) from 8.4.24 to 8.4.31. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.24...8.4.31) --- updated-dependencies: - dependency-name: postcss dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/integration/package-lock.json b/integration/package-lock.json index 195a333e0c..85c9cf965a 100644 --- a/integration/package-lock.json +++ b/integration/package-lock.json @@ -5835,9 +5835,9 @@ } }, "node_modules/postcss": { - "version": "8.4.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", - "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "dev": true, "funding": [ { From a863d6451eb1bb54673a86de79004f2182501ac1 Mon Sep 17 00:00:00 2001 From: "Hyukjoong (Chuck) Kim" Date: Thu, 5 Oct 2023 10:09:39 +0900 Subject: [PATCH 47/54] Add @interfaceObject and @composeDirective at Federation 2 directive lists. (#2821) Currently, in case of using `@interfaceObject`, in the graphql schema, it generates the directive template at the auto-generated file because those directives are not listed up and not excluded from the generation. So, it causes "not implemented" error on using @interfaceObject even this directive is federation 2.3 nested directive. This commit just adding those directives into the list. Signed-off-by: Hyukjoong Chuck Kim --- plugin/federation/federation.go | 8 +++++++- .../federation/testdata/federation2/federation2.graphql | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugin/federation/federation.go b/plugin/federation/federation.go index 99a1d312b0..7d98850315 100644 --- a/plugin/federation/federation.go +++ b/plugin/federation/federation.go @@ -85,6 +85,8 @@ func (f *federation) MutateConfig(cfg *config.Config) error { cfg.Directives["inaccessible"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["authenticated"] = config.DirectiveConfig{SkipRuntime: true} cfg.Directives["requiresScopes"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["interfaceObject"] = config.DirectiveConfig{SkipRuntime: true} + cfg.Directives["composeDirective"] = config.DirectiveConfig{SkipRuntime: true} } return nil @@ -183,7 +185,11 @@ func (f *federation) InjectSourceLate(schema *ast.Schema) *ast.Source { } entityResolverInputDefinitions += "input " + r.InputTypeName + " {\n" for _, keyField := range r.KeyFields { - entityResolverInputDefinitions += fmt.Sprintf("\t%s: %s\n", keyField.Field.ToGo(), keyField.Definition.Type.String()) + entityResolverInputDefinitions += fmt.Sprintf( + "\t%s: %s\n", + keyField.Field.ToGo(), + keyField.Definition.Type.String(), + ) } entityResolverInputDefinitions += "}" resolvers += fmt.Sprintf("\t%s(reps: [%s]!): [%s]\n", r.ResolverName, r.InputTypeName, e.Name) diff --git a/plugin/federation/testdata/federation2/federation2.graphql b/plugin/federation/testdata/federation2/federation2.graphql index 770f896970..5355cb804c 100644 --- a/plugin/federation/testdata/federation2/federation2.graphql +++ b/plugin/federation/testdata/federation2/federation2.graphql @@ -1,6 +1,6 @@ extend schema @link(url: "https://specs.apollo.dev/federation/v2.3", - import: ["@key", "@shareable", "@provides", "@external", "@tag", "@extends", "@override", "@inaccessible"]) + import: ["@key", "@shareable", "@provides", "@external", "@tag", "@extends", "@override", "@inaccessible", "@interfaceObject"]) schema { query: CustomQuery @@ -23,4 +23,3 @@ extend type ExternalExtension @key(fields: " upc ") { type CustomQuery { hello: Hello! } - From eed94e8caddb251cc6c180062b26708b8b06dd35 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Thu, 5 Oct 2023 12:36:27 -0400 Subject: [PATCH 48/54] release v0.17.39 --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index d718cd32af..5f3b12fb21 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 8a16e4e038..9326bac461 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index c1fffebd8a..601e030580 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index b33d5dbbc7..5266e68931 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index 43767d481b..d172e239cb 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index b2aba8e612..db466b42ba 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index 6c5f12be78..b8065fb4b5 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index ff97881b3e..6fb9a00ac2 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index a5c7fff00b..f5f64a5018 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" diff --git a/graphql/version.go b/graphql/version.go index 8a5f5646b8..38d27528b2 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.38-dev" +const Version = "v0.17.39" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index c284018666..c4d30c8f4b 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39 import ( "context" From 9c5fc3024574d0b954962d2e6453fa7489ba6327 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Thu, 5 Oct 2023 12:37:07 -0400 Subject: [PATCH 49/54] v0.17.39 postrelease bump --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index 5f3b12fb21..c81e4e09aa 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 9326bac461..ebeb0981e3 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index 601e030580..b6ddad1875 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 5266e68931..3d68de26fb 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index d172e239cb..81d1e1e81d 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index db466b42ba..7e4597385d 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index b8065fb4b5..1954ecd78f 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 6fb9a00ac2..26bd75998c 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index f5f64a5018..ce04d6a10c 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/graphql/version.go b/graphql/version.go index 38d27528b2..cf8db2360e 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.39" +const Version = "v0.17.39-dev" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index c4d30c8f4b..926757a1df 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.39 +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" From e5c17d63948dd20879e4a9db68863689842ab49a Mon Sep 17 00:00:00 2001 From: erankor Date: Sun, 15 Oct 2023 17:15:58 +0300 Subject: [PATCH 50/54] resolver: fix case-insensitive file name collision (#2829) for compatibility with Windows/Mac OS X, Go does not allow files with identical case-insensitive names. this commit changes the key of the 'files' map to use the lower case file name, keeping the original file name as a property on the File object. --- plugin/resolvergen/resolver.go | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/plugin/resolvergen/resolver.go b/plugin/resolvergen/resolver.go index d5515da35a..c3a2c40822 100644 --- a/plugin/resolvergen/resolver.go +++ b/plugin/resolvergen/resolver.go @@ -110,9 +110,12 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { for _, o := range objects { if o.HasResolvers() { - fn := gqlToResolverName(data.Config.Resolver.Dir(), o.Position.Src.Name, data.Config.Resolver.FilenameTemplate) + fnCase := gqlToResolverName(data.Config.Resolver.Dir(), o.Position.Src.Name, data.Config.Resolver.FilenameTemplate) + fn := strings.ToLower(fnCase) if files[fn] == nil { - files[fn] = &File{} + files[fn] = &File{ + name: fnCase, + } } caser := cases.Title(language.English, cases.NoLower) @@ -150,25 +153,28 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { } resolver := Resolver{o, f, rewriter.GetPrevDecl(structName, f.GoFieldName), comment, implementation} - fn := gqlToResolverName(data.Config.Resolver.Dir(), f.Position.Src.Name, data.Config.Resolver.FilenameTemplate) + fnCase := gqlToResolverName(data.Config.Resolver.Dir(), f.Position.Src.Name, data.Config.Resolver.FilenameTemplate) + fn := strings.ToLower(fnCase) if files[fn] == nil { - files[fn] = &File{} + files[fn] = &File{ + name: fnCase, + } } files[fn].Resolvers = append(files[fn].Resolvers, &resolver) } } - for filename, file := range files { - file.imports = rewriter.ExistingImports(filename) - file.RemainingSource = rewriter.RemainingSource(filename) + for _, file := range files { + file.imports = rewriter.ExistingImports(file.name) + file.RemainingSource = rewriter.RemainingSource(file.name) } newResolverTemplate := resolverTemplate if data.Config.Resolver.ResolverTemplate != "" { newResolverTemplate = readResolverTemplate(data.Config.Resolver.ResolverTemplate) } - for filename, file := range files { + for _, file := range files { resolverBuild := &ResolverBuild{ File: file, PackageName: data.Config.Resolver.Package, @@ -192,7 +198,7 @@ func (m *Plugin) generatePerSchema(data *codegen.Data) error { err := templates.Render(templates.Options{ PackageName: data.Config.Resolver.Package, FileNotice: fileNotice.String(), - Filename: filename, + Filename: file.name, Data: resolverBuild, Packages: data.Config.Packages, Template: newResolverTemplate, @@ -230,6 +236,7 @@ type ResolverBuild struct { } type File struct { + name string // These are separated because the type definition of the resolver object may live in a different file from the // resolver method implementations, for example when extending a type in a different graphql schema file Objects []*codegen.Object From 1e5fa72a260d2313cf2d2f3315c5f885aa209acd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 07:28:50 -0400 Subject: [PATCH 51/54] Bump @babel/traverse from 7.22.5 to 7.23.2 in /integration (#2831) Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.22.5 to 7.23.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse) --- updated-dependencies: - dependency-name: "@babel/traverse" dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- integration/package-lock.json | 163 +++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 50 deletions(-) diff --git a/integration/package-lock.json b/integration/package-lock.json index 85c9cf965a..21e629b5f7 100644 --- a/integration/package-lock.json +++ b/integration/package-lock.json @@ -202,17 +202,80 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.5.tgz", @@ -253,12 +316,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.5.tgz", - "integrity": "sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -322,22 +385,22 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -461,9 +524,9 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz", - "integrity": "sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { "@babel/types": "^7.22.5" @@ -482,9 +545,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -514,13 +577,13 @@ } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -590,9 +653,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", - "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1038,33 +1101,33 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.5.tgz", - "integrity": "sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1073,13 +1136,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { From 74e918f9271dbd045a0425e1f6ddb4804e30404b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Endika=20Guti=C3=A9rrez?= Date: Thu, 19 Oct 2023 13:35:14 +0200 Subject: [PATCH 52/54] Map based input types fields are now coerced to the right type (#2830) * Input maps now unmarshals and checks nested fields * Added unit tests * Tested required fields in input maps * Docs updated with disclaimer * Added test for nested inputs --- api/testdata/federation2/graph/generated.go | 17 - codegen/config/binder.go | 4 + codegen/input.gotpl | 23 +- codegen/object.go | 8 +- .../testserver/followschema/maps.generated.go | 311 +++++++++++++- codegen/testserver/followschema/maps.go | 28 ++ codegen/testserver/followschema/maps.graphql | 16 +- codegen/testserver/followschema/maps_test.go | 37 +- .../followschema/root_.generated.go | 34 +- .../followschema/schema.generated.go | 49 ++- codegen/testserver/singlefile/generated.go | 394 +++++++++++++++++- codegen/testserver/singlefile/maps.go | 28 ++ codegen/testserver/singlefile/maps.graphql | 16 +- codegen/testserver/singlefile/maps_test.go | 37 +- codegen/type.gotpl | 4 +- docs/content/reference/changesets.md | 5 +- .../filetemplate/out/schema.custom.go | 8 +- .../followschema/out/schema.resolvers.go | 8 +- .../out/schema.resolvers.go | 2 +- .../resolvertemplate/out/schema.resolvers.go | 2 +- 20 files changed, 971 insertions(+), 60 deletions(-) create mode 100644 codegen/testserver/followschema/maps.go create mode 100644 codegen/testserver/singlefile/maps.go diff --git a/api/testdata/federation2/graph/generated.go b/api/testdata/federation2/graph/generated.go index 7c3dc934ff..4e6932e824 100644 --- a/api/testdata/federation2/graph/generated.go +++ b/api/testdata/federation2/graph/generated.go @@ -45,8 +45,6 @@ type ResolverRoot interface { } type DirectiveRoot struct { - ComposeDirective func(ctx context.Context, obj interface{}, next graphql.Resolver, name string) (res interface{}, err error) - InterfaceObject func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) } type ComplexityRoot struct { @@ -355,21 +353,6 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** -func (ec *executionContext) dir_composeDirective_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["name"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("name")) - arg0, err = ec.unmarshalNString2string(ctx, tmp) - if err != nil { - return nil, err - } - } - args["name"] = arg0 - return args, nil -} - func (ec *executionContext) field_Mutation_createTodo_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} diff --git a/codegen/config/binder.go b/codegen/config/binder.go index 22cc855db0..dd25d6f5e6 100644 --- a/codegen/config/binder.go +++ b/codegen/config/binder.go @@ -274,6 +274,10 @@ func (ref *TypeReference) IsScalar() bool { return ref.Definition.Kind == ast.Scalar } +func (ref *TypeReference) IsMap() bool { + return ref.GO == MapType +} + func (ref *TypeReference) UniquenessKey() string { nullability := "O" if ref.GQL.NonNull { diff --git a/codegen/input.gotpl b/codegen/input.gotpl index 126ff661c3..f4ba90d907 100644 --- a/codegen/input.gotpl +++ b/codegen/input.gotpl @@ -5,7 +5,11 @@ {{- $it = "&it" }} {{- end }} func (ec *executionContext) unmarshalInput{{ .Name }}(ctx context.Context, obj interface{}) ({{ if .PointersInUmarshalInput }}*{{ end }}{{.Type | ref}}, error) { - var it {{.Type | ref}} + {{- if $input.IsMap }} + it := make(map[string]interface{}, len(obj.(map[string]interface{}))) + {{- else }} + var it {{.Type | ref}} + {{- end }} asMap := map[string]interface{}{} for k, v := range obj.(map[string]interface{}) { asMap[k] = v @@ -29,6 +33,11 @@ case {{$field.Name|quote}}: var err error + {{- $lhs := (printf "it.%s" $field.GoFieldName) }} + {{- if $input.IsMap }} + {{- $lhs = (printf "it[%q]" $field.Name) }} + {{- end }} + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField({{$field.Name|quote}})) {{- if $field.ImplDirectives }} directive0 := func(ctx context.Context) (interface{}, error) { return ec.{{ $field.TypeReference.UnmarshalFunc }}(ctx, v) } @@ -44,18 +53,18 @@ } {{- else }} {{- if $field.TypeReference.IsOmittable }} - it.{{$field.GoFieldName}} = graphql.OmittableOf(data) + {{ $lhs }} = graphql.OmittableOf(data) {{- else }} - it.{{$field.GoFieldName}} = data + {{ $lhs }} = data {{- end }} {{- end }} {{- if $field.TypeReference.IsNilable }} {{- if not $field.IsResolver }} } else if tmp == nil { {{- if $field.TypeReference.IsOmittable }} - it.{{$field.GoFieldName}} = graphql.OmittableOf[{{ $field.TypeReference.GO | ref }}](nil) + {{ $lhs }} = graphql.OmittableOf[{{ $field.TypeReference.GO | ref }}](nil) {{- else }} - it.{{$field.GoFieldName}} = nil + {{ $lhs }} = nil {{- end }} {{- end }} {{- end }} @@ -78,9 +87,9 @@ return {{$it}}, err } {{- if $field.TypeReference.IsOmittable }} - it.{{$field.GoFieldName}} = graphql.OmittableOf(data) + {{ $lhs }} = graphql.OmittableOf(data) {{- else }} - it.{{$field.GoFieldName}} = data + {{ $lhs }} = data {{- end }} {{- end }} {{- end }} diff --git a/codegen/object.go b/codegen/object.go index 7164560e10..97575f30a8 100644 --- a/codegen/object.go +++ b/codegen/object.go @@ -113,8 +113,8 @@ func (o *Object) HasResolvers() bool { } func (o *Object) HasUnmarshal() bool { - if o.Type == config.MapType { - return true + if o.IsMap() { + return false } for i := 0; i < o.Type.(*types.Named).NumMethods(); i++ { if o.Type.(*types.Named).Method(i).Name() == "UnmarshalGQL" { @@ -150,6 +150,10 @@ func (o *Object) IsReserved() bool { return strings.HasPrefix(o.Definition.Name, "__") } +func (o *Object) IsMap() bool { + return o.Type == config.MapType +} + func (o *Object) Description() string { return o.Definition.Description } diff --git a/codegen/testserver/followschema/maps.generated.go b/codegen/testserver/followschema/maps.generated.go index 7fcd91fc1f..d2c4e1b885 100644 --- a/codegen/testserver/followschema/maps.generated.go +++ b/codegen/testserver/followschema/maps.generated.go @@ -27,6 +27,47 @@ import ( // region **************************** field.gotpl ***************************** +func (ec *executionContext) _MapNested_value(ctx context.Context, field graphql.CollectedField, obj *MapNested) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MapNested_value(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 := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Value, nil + }) + + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(CustomScalar) + fc.Result = res + return ec.marshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MapNested_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MapNested", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type CustomScalar does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _MapStringInterfaceType_a(ctx context.Context, field graphql.CollectedField, obj map[string]interface{}) (ret graphql.Marshaler) { fc, err := ec.fieldContext_MapStringInterfaceType_a(ctx, field) if err != nil { @@ -121,10 +162,193 @@ func (ec *executionContext) fieldContext_MapStringInterfaceType_b(ctx context.Co return fc, nil } +func (ec *executionContext) _MapStringInterfaceType_c(ctx context.Context, field graphql.CollectedField, obj map[string]interface{}) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MapStringInterfaceType_c(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 := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + switch v := obj["c"].(type) { + case *CustomScalar: + return v, nil + case CustomScalar: + return &v, nil + case nil: + return (*CustomScalar)(nil), nil + default: + return nil, fmt.Errorf("unexpected type %T for field %s", v, "c") + } + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*CustomScalar) + fc.Result = res + return ec.marshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MapStringInterfaceType_c(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MapStringInterfaceType", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type CustomScalar does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _MapStringInterfaceType_nested(ctx context.Context, field graphql.CollectedField, obj map[string]interface{}) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MapStringInterfaceType_nested(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 := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + switch v := obj["nested"].(type) { + case *MapNested: + return v, nil + case MapNested: + return &v, nil + case nil: + return (*MapNested)(nil), nil + default: + return nil, fmt.Errorf("unexpected type %T for field %s", v, "nested") + } + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*MapNested) + fc.Result = res + return ec.marshalOMapNested2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐMapNested(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MapStringInterfaceType_nested(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MapStringInterfaceType", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "value": + return ec.fieldContext_MapNested_value(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type MapNested", field.Name) + }, + } + return fc, nil +} + // endregion **************************** field.gotpl ***************************** // region **************************** input.gotpl ***************************** +func (ec *executionContext) unmarshalInputMapNestedInput(ctx context.Context, obj interface{}) (MapNested, error) { + var it MapNested + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"value"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "value": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("value")) + data, err := ec.unmarshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx, v) + if err != nil { + return it, err + } + it.Value = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputMapStringInterfaceInput(ctx context.Context, obj interface{}) (map[string]interface{}, error) { + it := make(map[string]interface{}, len(obj.(map[string]interface{}))) + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"a", "b", "c", "nested"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "a": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("a")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it["a"] = data + case "b": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("b")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it["b"] = data + case "c": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("c")) + data, err := ec.unmarshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx, v) + if err != nil { + return it, err + } + it["c"] = data + case "nested": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nested")) + data, err := ec.unmarshalOMapNestedInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐMapNested(ctx, v) + if err != nil { + return it, err + } + it["nested"] = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputNestedMapInput(ctx context.Context, obj interface{}) (NestedMapInput, error) { var it NestedMapInput asMap := map[string]interface{}{} @@ -162,6 +386,45 @@ func (ec *executionContext) unmarshalInputNestedMapInput(ctx context.Context, ob // region **************************** object.gotpl **************************** +var mapNestedImplementors = []string{"MapNested"} + +func (ec *executionContext) _MapNested(ctx context.Context, sel ast.SelectionSet, obj *MapNested) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mapNestedImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MapNested") + case "value": + out.Values[i] = ec._MapNested_value(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + var mapStringInterfaceTypeImplementors = []string{"MapStringInterfaceType"} func (ec *executionContext) _MapStringInterfaceType(ctx context.Context, sel ast.SelectionSet, obj map[string]interface{}) graphql.Marshaler { @@ -177,6 +440,10 @@ func (ec *executionContext) _MapStringInterfaceType(ctx context.Context, sel ast out.Values[i] = ec._MapStringInterfaceType_a(ctx, field, obj) case "b": out.Values[i] = ec._MapStringInterfaceType_b(ctx, field, obj) + case "c": + out.Values[i] = ec._MapStringInterfaceType_c(ctx, field, obj) + case "nested": + out.Values[i] = ec._MapStringInterfaceType_nested(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -204,11 +471,53 @@ func (ec *executionContext) _MapStringInterfaceType(ctx context.Context, sel ast // region ***************************** type.gotpl ***************************** +func (ec *executionContext) unmarshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx context.Context, v interface{}) (CustomScalar, error) { + var res CustomScalar + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx context.Context, sel ast.SelectionSet, v CustomScalar) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx context.Context, v interface{}) (*CustomScalar, error) { + if v == nil { + return nil, nil + } + var res = new(CustomScalar) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐCustomScalar(ctx context.Context, sel ast.SelectionSet, v *CustomScalar) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) marshalOMapNested2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐMapNested(ctx context.Context, sel ast.SelectionSet, v *MapNested) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._MapNested(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOMapNestedInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚐMapNested(ctx context.Context, v interface{}) (*MapNested, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMapNestedInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOMapStringInterfaceInput2map(ctx context.Context, v interface{}) (map[string]interface{}, error) { if v == nil { return nil, nil } - return v.(map[string]interface{}), nil + res, err := ec.unmarshalInputMapStringInterfaceInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOMapStringInterfaceType2map(ctx context.Context, sel ast.SelectionSet, v map[string]interface{}) graphql.Marshaler { diff --git a/codegen/testserver/followschema/maps.go b/codegen/testserver/followschema/maps.go new file mode 100644 index 0000000000..871aabf3e6 --- /dev/null +++ b/codegen/testserver/followschema/maps.go @@ -0,0 +1,28 @@ +package followschema + +import ( + "io" + "strconv" +) + +type MapNested struct { + Value CustomScalar +} + +type CustomScalar struct { + value int64 +} + +func (s *CustomScalar) UnmarshalGQL(v interface{}) (err error) { + switch v := v.(type) { + case string: + s.value, err = strconv.ParseInt(v, 10, 64) + case int64: + s.value = v + } + return +} + +func (s CustomScalar) MarshalGQL(w io.Writer) { + _, _ = w.Write([]byte(strconv.Quote(strconv.FormatInt(s.value, 10)))) +} diff --git a/codegen/testserver/followschema/maps.graphql b/codegen/testserver/followschema/maps.graphql index 0fd639b0c4..51eac074ab 100644 --- a/codegen/testserver/followschema/maps.graphql +++ b/codegen/testserver/followschema/maps.graphql @@ -6,13 +6,27 @@ extend type Query { type MapStringInterfaceType @goModel(model: "map[string]interface{}") { a: String b: Int + c: CustomScalar + nested: MapNested +} + +type MapNested @goModel(model: "followschema.MapNested") { + value: CustomScalar! } input MapStringInterfaceInput @goModel(model: "map[string]interface{}") { - a: String + a: String! b: Int + c: CustomScalar + nested: MapNestedInput } +input MapNestedInput @goModel(model: "followschema.MapNested") { + value: CustomScalar! +} + +scalar CustomScalar @goModel(model: "followschema.CustomScalar") + input NestedMapInput { map: MapStringInterfaceInput } diff --git a/codegen/testserver/followschema/maps_test.go b/codegen/testserver/followschema/maps_test.go index 314dc6055d..58b559c16a 100644 --- a/codegen/testserver/followschema/maps_test.go +++ b/codegen/testserver/followschema/maps_test.go @@ -13,12 +13,14 @@ import ( func TestMaps(t *testing.T) { resolver := &Stub{} resolver.QueryResolver.MapStringInterface = func(ctx context.Context, in map[string]interface{}) (i map[string]interface{}, e error) { + validateMapItemsType(t, in) return in, nil } resolver.QueryResolver.MapNestedStringInterface = func(ctx context.Context, in *NestedMapInput) (i map[string]interface{}, e error) { if in == nil { return nil, nil } + validateMapItemsType(t, in.Map) return in.Map, nil } @@ -29,7 +31,7 @@ func TestMaps(t *testing.T) { var resp struct { MapStringInterface map[string]interface{} } - err := c.Post(`query { mapStringInterface { a, b } }`, &resp) + err := c.Post(`query { mapStringInterface { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Nil(t, resp.MapStringInterface) }) @@ -38,7 +40,7 @@ func TestMaps(t *testing.T) { var resp struct { MapStringInterface map[string]interface{} } - err := c.Post(`query { mapStringInterface(in: null) { a, b } }`, &resp) + err := c.Post(`query { mapStringInterface(in: null) { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Nil(t, resp.MapStringInterface) }) @@ -47,28 +49,53 @@ func TestMaps(t *testing.T) { var resp struct { MapStringInterface map[string]interface{} } - err := c.Post(`query { mapStringInterface(in: { a: "a", b: null }) { a, b } }`, &resp) + err := c.Post(`query($value: CustomScalar!) { mapStringInterface(in: { a: "a", b: null, c: 42, nested: { value: $value } }) { a, b, c, nested { value } } }`, &resp, client.Var("value", "17")) require.NoError(t, err) require.Equal(t, "a", resp.MapStringInterface["a"]) require.Nil(t, resp.MapStringInterface["b"]) + require.Equal(t, "42", resp.MapStringInterface["c"]) + require.NotNil(t, resp.MapStringInterface["nested"]) + require.IsType(t, map[string]interface{}{}, resp.MapStringInterface["nested"]) + require.Equal(t, "17", (resp.MapStringInterface["nested"].(map[string]interface{}))["value"]) }) t.Run("nested", func(t *testing.T) { var resp struct { MapNestedStringInterface map[string]interface{} } - err := c.Post(`query { mapNestedStringInterface(in: { map: { a: "a", b: null } }) { a, b } }`, &resp) + err := c.Post(`query { mapNestedStringInterface(in: { map: { a: "a", c: "42", nested: { value: 31 } } }) { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Equal(t, "a", resp.MapNestedStringInterface["a"]) require.Nil(t, resp.MapNestedStringInterface["b"]) + require.Equal(t, "42", resp.MapNestedStringInterface["c"]) + require.NotNil(t, resp.MapNestedStringInterface["nested"]) + require.IsType(t, map[string]interface{}{}, resp.MapNestedStringInterface["nested"]) + require.Equal(t, "31", (resp.MapNestedStringInterface["nested"].(map[string]interface{}))["value"]) }) t.Run("nested nil", func(t *testing.T) { var resp struct { MapNestedStringInterface map[string]interface{} } - err := c.Post(`query { mapNestedStringInterface(in: { map: null }) { a, b } }`, &resp) + err := c.Post(`query { mapNestedStringInterface(in: { map: null }) { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Nil(t, resp.MapNestedStringInterface) }) } + +func validateMapItemsType(t *testing.T, in map[string]interface{}) { + for k, v := range in { + switch k { + case "a": + require.IsType(t, "", v) + case "b": + require.IsType(t, new(int), v) + case "c": + require.IsType(t, new(CustomScalar), v) + case "nested": + require.IsType(t, new(MapNested), v) + default: + require.Failf(t, "unexpected key in map", "key %q was not expected in map", k) + } + } +} diff --git a/codegen/testserver/followschema/root_.generated.go b/codegen/testserver/followschema/root_.generated.go index 467c7e981c..8463011b31 100644 --- a/codegen/testserver/followschema/root_.generated.go +++ b/codegen/testserver/followschema/root_.generated.go @@ -226,9 +226,15 @@ type ComplexityRoot struct { ID func(childComplexity int) int } + MapNested struct { + Value func(childComplexity int) int + } + MapStringInterfaceType struct { - A func(childComplexity int) int - B func(childComplexity int) int + A func(childComplexity int) int + B func(childComplexity int) int + C func(childComplexity int) int + Nested func(childComplexity int) int } ModelMethods struct { @@ -899,6 +905,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Map.ID(childComplexity), true + case "MapNested.value": + if e.complexity.MapNested.Value == nil { + break + } + + return e.complexity.MapNested.Value(childComplexity), true + case "MapStringInterfaceType.a": if e.complexity.MapStringInterfaceType.A == nil { break @@ -913,6 +926,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MapStringInterfaceType.B(childComplexity), true + case "MapStringInterfaceType.c": + if e.complexity.MapStringInterfaceType.C == nil { + break + } + + return e.complexity.MapStringInterfaceType.C(childComplexity), true + + case "MapStringInterfaceType.nested": + if e.complexity.MapStringInterfaceType.Nested == nil { + break + } + + return e.complexity.MapStringInterfaceType.Nested(childComplexity), true + case "ModelMethods.noContext": if e.complexity.ModelMethods.NoContext == nil { break @@ -2090,12 +2117,15 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { rc := graphql.GetOperationContext(ctx) ec := executionContext{rc, e, 0, 0, make(chan graphql.DeferredResult)} inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputChanges, ec.unmarshalInputDefaultInput, ec.unmarshalInputFieldsOrderInput, ec.unmarshalInputInnerDirectives, ec.unmarshalInputInnerInput, ec.unmarshalInputInputDirectives, ec.unmarshalInputInputWithEnumValue, + ec.unmarshalInputMapNestedInput, + ec.unmarshalInputMapStringInterfaceInput, ec.unmarshalInputNestedInput, ec.unmarshalInputNestedMapInput, ec.unmarshalInputOmittableInput, diff --git a/codegen/testserver/followschema/schema.generated.go b/codegen/testserver/followschema/schema.generated.go index 0af031ea71..01387a495d 100644 --- a/codegen/testserver/followschema/schema.generated.go +++ b/codegen/testserver/followschema/schema.generated.go @@ -3610,6 +3610,10 @@ func (ec *executionContext) fieldContext_Query_mapStringInterface(ctx context.Co return ec.fieldContext_MapStringInterfaceType_a(ctx, field) case "b": return ec.fieldContext_MapStringInterfaceType_b(ctx, field) + case "c": + return ec.fieldContext_MapStringInterfaceType_c(ctx, field) + case "nested": + return ec.fieldContext_MapStringInterfaceType_nested(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type MapStringInterfaceType", field.Name) }, @@ -3665,6 +3669,10 @@ func (ec *executionContext) fieldContext_Query_mapNestedStringInterface(ctx cont return ec.fieldContext_MapStringInterfaceType_a(ctx, field) case "b": return ec.fieldContext_MapStringInterfaceType_b(ctx, field) + case "c": + return ec.fieldContext_MapStringInterfaceType_c(ctx, field) + case "nested": + return ec.fieldContext_MapStringInterfaceType_nested(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type MapStringInterfaceType", field.Name) }, @@ -5761,6 +5769,44 @@ func (ec *executionContext) fieldContext_User_pets(ctx context.Context, field gr // region **************************** input.gotpl ***************************** +func (ec *executionContext) unmarshalInputChanges(ctx context.Context, obj interface{}) (map[string]interface{}, error) { + it := make(map[string]interface{}, len(obj.(map[string]interface{}))) + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"a", "b"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "a": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("a")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it["a"] = data + case "b": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("b")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it["b"] = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputInnerInput(ctx context.Context, obj interface{}) (InnerInput, error) { var it InnerInput asMap := map[string]interface{}{} @@ -8220,7 +8266,8 @@ func (ec *executionContext) unmarshalOChanges2map(ctx context.Context, v interfa if v == nil { return nil, nil } - return v.(map[string]interface{}), nil + res, err := ec.unmarshalInputChanges(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOInvalidIdentifier2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋfollowschemaᚋinvalidᚑpackagenameᚐInvalidIdentifier(ctx context.Context, sel ast.SelectionSet, v *invalid_packagename.InvalidIdentifier) graphql.Marshaler { diff --git a/codegen/testserver/singlefile/generated.go b/codegen/testserver/singlefile/generated.go index 401b42a8fa..f260711bfb 100644 --- a/codegen/testserver/singlefile/generated.go +++ b/codegen/testserver/singlefile/generated.go @@ -235,9 +235,15 @@ type ComplexityRoot struct { ID func(childComplexity int) int } + MapNested struct { + Value func(childComplexity int) int + } + MapStringInterfaceType struct { - A func(childComplexity int) int - B func(childComplexity int) int + A func(childComplexity int) int + B func(childComplexity int) int + C func(childComplexity int) int + Nested func(childComplexity int) int } ModelMethods struct { @@ -1051,6 +1057,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Map.ID(childComplexity), true + case "MapNested.value": + if e.complexity.MapNested.Value == nil { + break + } + + return e.complexity.MapNested.Value(childComplexity), true + case "MapStringInterfaceType.a": if e.complexity.MapStringInterfaceType.A == nil { break @@ -1065,6 +1078,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MapStringInterfaceType.B(childComplexity), true + case "MapStringInterfaceType.c": + if e.complexity.MapStringInterfaceType.C == nil { + break + } + + return e.complexity.MapStringInterfaceType.C(childComplexity), true + + case "MapStringInterfaceType.nested": + if e.complexity.MapStringInterfaceType.Nested == nil { + break + } + + return e.complexity.MapStringInterfaceType.Nested(childComplexity), true + case "ModelMethods.noContext": if e.complexity.ModelMethods.NoContext == nil { break @@ -2242,12 +2269,15 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { rc := graphql.GetOperationContext(ctx) ec := executionContext{rc, e, 0, 0, make(chan graphql.DeferredResult)} inputUnmarshalMap := graphql.BuildUnmarshalerMap( + ec.unmarshalInputChanges, ec.unmarshalInputDefaultInput, ec.unmarshalInputFieldsOrderInput, ec.unmarshalInputInnerDirectives, ec.unmarshalInputInnerInput, ec.unmarshalInputInputDirectives, ec.unmarshalInputInputWithEnumValue, + ec.unmarshalInputMapNestedInput, + ec.unmarshalInputMapStringInterfaceInput, ec.unmarshalInputNestedInput, ec.unmarshalInputNestedMapInput, ec.unmarshalInputOmittableInput, @@ -6053,6 +6083,47 @@ func (ec *executionContext) fieldContext_Map_id(ctx context.Context, field graph return fc, nil } +func (ec *executionContext) _MapNested_value(ctx context.Context, field graphql.CollectedField, obj *MapNested) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MapNested_value(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 := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Value, nil + }) + + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(CustomScalar) + fc.Result = res + return ec.marshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MapNested_value(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MapNested", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type CustomScalar does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) _MapStringInterfaceType_a(ctx context.Context, field graphql.CollectedField, obj map[string]interface{}) (ret graphql.Marshaler) { fc, err := ec.fieldContext_MapStringInterfaceType_a(ctx, field) if err != nil { @@ -6147,6 +6218,104 @@ func (ec *executionContext) fieldContext_MapStringInterfaceType_b(ctx context.Co return fc, nil } +func (ec *executionContext) _MapStringInterfaceType_c(ctx context.Context, field graphql.CollectedField, obj map[string]interface{}) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MapStringInterfaceType_c(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 := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + switch v := obj["c"].(type) { + case *CustomScalar: + return v, nil + case CustomScalar: + return &v, nil + case nil: + return (*CustomScalar)(nil), nil + default: + return nil, fmt.Errorf("unexpected type %T for field %s", v, "c") + } + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*CustomScalar) + fc.Result = res + return ec.marshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MapStringInterfaceType_c(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MapStringInterfaceType", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type CustomScalar does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _MapStringInterfaceType_nested(ctx context.Context, field graphql.CollectedField, obj map[string]interface{}) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_MapStringInterfaceType_nested(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 := ec._fieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + switch v := obj["nested"].(type) { + case *MapNested: + return v, nil + case MapNested: + return &v, nil + case nil: + return (*MapNested)(nil), nil + default: + return nil, fmt.Errorf("unexpected type %T for field %s", v, "nested") + } + }) + + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*MapNested) + fc.Result = res + return ec.marshalOMapNested2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐMapNested(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_MapStringInterfaceType_nested(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "MapStringInterfaceType", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "value": + return ec.fieldContext_MapNested_value(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type MapNested", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _ModelMethods_resolverField(ctx context.Context, field graphql.CollectedField, obj *ModelMethods) (ret graphql.Marshaler) { fc, err := ec.fieldContext_ModelMethods_resolverField(ctx, field) if err != nil { @@ -9896,6 +10065,10 @@ func (ec *executionContext) fieldContext_Query_mapStringInterface(ctx context.Co return ec.fieldContext_MapStringInterfaceType_a(ctx, field) case "b": return ec.fieldContext_MapStringInterfaceType_b(ctx, field) + case "c": + return ec.fieldContext_MapStringInterfaceType_c(ctx, field) + case "nested": + return ec.fieldContext_MapStringInterfaceType_nested(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type MapStringInterfaceType", field.Name) }, @@ -9951,6 +10124,10 @@ func (ec *executionContext) fieldContext_Query_mapNestedStringInterface(ctx cont return ec.fieldContext_MapStringInterfaceType_a(ctx, field) case "b": return ec.fieldContext_MapStringInterfaceType_b(ctx, field) + case "c": + return ec.fieldContext_MapStringInterfaceType_c(ctx, field) + case "nested": + return ec.fieldContext_MapStringInterfaceType_nested(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type MapStringInterfaceType", field.Name) }, @@ -14775,6 +14952,44 @@ func (ec *executionContext) fieldContext_iIt_id(ctx context.Context, field graph // region **************************** input.gotpl ***************************** +func (ec *executionContext) unmarshalInputChanges(ctx context.Context, obj interface{}) (map[string]interface{}, error) { + it := make(map[string]interface{}, len(obj.(map[string]interface{}))) + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"a", "b"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "a": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("a")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it["a"] = data + case "b": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("b")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it["b"] = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputDefaultInput(ctx context.Context, obj interface{}) (DefaultInput, error) { var it DefaultInput asMap := map[string]interface{}{} @@ -15150,6 +15365,91 @@ func (ec *executionContext) unmarshalInputInputWithEnumValue(ctx context.Context return it, nil } +func (ec *executionContext) unmarshalInputMapNestedInput(ctx context.Context, obj interface{}) (MapNested, error) { + var it MapNested + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"value"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "value": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("value")) + data, err := ec.unmarshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx, v) + if err != nil { + return it, err + } + it.Value = data + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputMapStringInterfaceInput(ctx context.Context, obj interface{}) (map[string]interface{}, error) { + it := make(map[string]interface{}, len(obj.(map[string]interface{}))) + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"a", "b", "c", "nested"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "a": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("a")) + data, err := ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + it["a"] = data + case "b": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("b")) + data, err := ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + it["b"] = data + case "c": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("c")) + data, err := ec.unmarshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx, v) + if err != nil { + return it, err + } + it["c"] = data + case "nested": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("nested")) + data, err := ec.unmarshalOMapNestedInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐMapNested(ctx, v) + if err != nil { + return it, err + } + it["nested"] = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputNestedInput(ctx context.Context, obj interface{}) (NestedInput, error) { var it NestedInput asMap := map[string]interface{}{} @@ -17449,6 +17749,45 @@ func (ec *executionContext) _Map(ctx context.Context, sel ast.SelectionSet, obj return out } +var mapNestedImplementors = []string{"MapNested"} + +func (ec *executionContext) _MapNested(ctx context.Context, sel ast.SelectionSet, obj *MapNested) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mapNestedImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MapNested") + case "value": + out.Values[i] = ec._MapNested_value(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + 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 +} + var mapStringInterfaceTypeImplementors = []string{"MapStringInterfaceType"} func (ec *executionContext) _MapStringInterfaceType(ctx context.Context, sel ast.SelectionSet, obj map[string]interface{}) graphql.Marshaler { @@ -17464,6 +17803,10 @@ func (ec *executionContext) _MapStringInterfaceType(ctx context.Context, sel ast out.Values[i] = ec._MapStringInterfaceType_a(ctx, field, obj) case "b": out.Values[i] = ec._MapStringInterfaceType_b(ctx, field, obj) + case "c": + out.Values[i] = ec._MapStringInterfaceType_c(ctx, field, obj) + case "nested": + out.Values[i] = ec._MapStringInterfaceType_nested(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -21102,6 +21445,16 @@ func (ec *executionContext) marshalNCheckIssue8962ᚖgithubᚗcomᚋ99designsᚋ return ec._CheckIssue896(ctx, sel, v) } +func (ec *executionContext) unmarshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx context.Context, v interface{}) (CustomScalar, error) { + var res CustomScalar + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCustomScalar2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx context.Context, sel ast.SelectionSet, v CustomScalar) graphql.Marshaler { + return v +} + func (ec *executionContext) unmarshalNDefaultInput2githubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐDefaultInput(ctx context.Context, v interface{}) (DefaultInput, error) { res, err := ec.unmarshalInputDefaultInput(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -22205,7 +22558,8 @@ func (ec *executionContext) unmarshalOChanges2map(ctx context.Context, v interfa if v == nil { return nil, nil } - return v.(map[string]interface{}), nil + res, err := ec.unmarshalInputChanges(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOCheckIssue8962ᚕᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCheckIssue896(ctx context.Context, sel ast.SelectionSet, v []*CheckIssue896) graphql.Marshaler { @@ -22314,6 +22668,22 @@ func (ec *executionContext) marshalOCoordinates2githubᚗcomᚋ99designsᚋgqlge return ec._Coordinates(ctx, sel, &v) } +func (ec *executionContext) unmarshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx context.Context, v interface{}) (*CustomScalar, error) { + if v == nil { + return nil, nil + } + var res = new(CustomScalar) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOCustomScalar2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐCustomScalar(ctx context.Context, sel ast.SelectionSet, v *CustomScalar) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + func (ec *executionContext) unmarshalODefaultScalarImplementation2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil @@ -22594,11 +22964,27 @@ func (ec *executionContext) marshalOIt2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋco return ec._It(ctx, sel, v) } +func (ec *executionContext) marshalOMapNested2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐMapNested(ctx context.Context, sel ast.SelectionSet, v *MapNested) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._MapNested(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOMapNestedInput2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋcodegenᚋtestserverᚋsinglefileᚐMapNested(ctx context.Context, v interface{}) (*MapNested, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputMapNestedInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOMapStringInterfaceInput2map(ctx context.Context, v interface{}) (map[string]interface{}, error) { if v == nil { return nil, nil } - return v.(map[string]interface{}), nil + res, err := ec.unmarshalInputMapStringInterfaceInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) } func (ec *executionContext) marshalOMapStringInterfaceType2map(ctx context.Context, sel ast.SelectionSet, v map[string]interface{}) graphql.Marshaler { diff --git a/codegen/testserver/singlefile/maps.go b/codegen/testserver/singlefile/maps.go new file mode 100644 index 0000000000..58366271b9 --- /dev/null +++ b/codegen/testserver/singlefile/maps.go @@ -0,0 +1,28 @@ +package singlefile + +import ( + "io" + "strconv" +) + +type MapNested struct { + Value CustomScalar +} + +type CustomScalar struct { + value int64 +} + +func (s *CustomScalar) UnmarshalGQL(v interface{}) (err error) { + switch v := v.(type) { + case string: + s.value, err = strconv.ParseInt(v, 10, 64) + case int64: + s.value = v + } + return +} + +func (s CustomScalar) MarshalGQL(w io.Writer) { + _, _ = w.Write([]byte(strconv.Quote(strconv.FormatInt(s.value, 10)))) +} diff --git a/codegen/testserver/singlefile/maps.graphql b/codegen/testserver/singlefile/maps.graphql index 0fd639b0c4..38205ad2ac 100644 --- a/codegen/testserver/singlefile/maps.graphql +++ b/codegen/testserver/singlefile/maps.graphql @@ -6,13 +6,27 @@ extend type Query { type MapStringInterfaceType @goModel(model: "map[string]interface{}") { a: String b: Int + c: CustomScalar + nested: MapNested +} + +type MapNested @goModel(model: "singlefile.MapNested") { + value: CustomScalar! } input MapStringInterfaceInput @goModel(model: "map[string]interface{}") { - a: String + a: String! b: Int + c: CustomScalar + nested: MapNestedInput } +input MapNestedInput @goModel(model: "singlefile.MapNested") { + value: CustomScalar! +} + +scalar CustomScalar @goModel(model: "singlefile.CustomScalar") + input NestedMapInput { map: MapStringInterfaceInput } diff --git a/codegen/testserver/singlefile/maps_test.go b/codegen/testserver/singlefile/maps_test.go index 1c9cbb465f..1b532909fb 100644 --- a/codegen/testserver/singlefile/maps_test.go +++ b/codegen/testserver/singlefile/maps_test.go @@ -13,12 +13,14 @@ import ( func TestMaps(t *testing.T) { resolver := &Stub{} resolver.QueryResolver.MapStringInterface = func(ctx context.Context, in map[string]interface{}) (i map[string]interface{}, e error) { + validateMapItemsType(t, in) return in, nil } resolver.QueryResolver.MapNestedStringInterface = func(ctx context.Context, in *NestedMapInput) (i map[string]interface{}, e error) { if in == nil { return nil, nil } + validateMapItemsType(t, in.Map) return in.Map, nil } @@ -29,7 +31,7 @@ func TestMaps(t *testing.T) { var resp struct { MapStringInterface map[string]interface{} } - err := c.Post(`query { mapStringInterface { a, b } }`, &resp) + err := c.Post(`query { mapStringInterface { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Nil(t, resp.MapStringInterface) }) @@ -38,7 +40,7 @@ func TestMaps(t *testing.T) { var resp struct { MapStringInterface map[string]interface{} } - err := c.Post(`query { mapStringInterface(in: null) { a, b } }`, &resp) + err := c.Post(`query { mapStringInterface(in: null) { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Nil(t, resp.MapStringInterface) }) @@ -47,28 +49,53 @@ func TestMaps(t *testing.T) { var resp struct { MapStringInterface map[string]interface{} } - err := c.Post(`query { mapStringInterface(in: { a: "a", b: null }) { a, b } }`, &resp) + err := c.Post(`query($value: CustomScalar!) { mapStringInterface(in: { a: "a", b: null, c: 42, nested: { value: $value } }) { a, b, c, nested { value } } }`, &resp, client.Var("value", "17")) require.NoError(t, err) require.Equal(t, "a", resp.MapStringInterface["a"]) require.Nil(t, resp.MapStringInterface["b"]) + require.Equal(t, "42", resp.MapStringInterface["c"]) + require.NotNil(t, resp.MapStringInterface["nested"]) + require.IsType(t, map[string]interface{}{}, resp.MapStringInterface["nested"]) + require.Equal(t, "17", (resp.MapStringInterface["nested"].(map[string]interface{}))["value"]) }) t.Run("nested", func(t *testing.T) { var resp struct { MapNestedStringInterface map[string]interface{} } - err := c.Post(`query { mapNestedStringInterface(in: { map: { a: "a", b: null } }) { a, b } }`, &resp) + err := c.Post(`query { mapNestedStringInterface(in: { map: { a: "a", c: "42", nested: { value: 31 } } }) { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Equal(t, "a", resp.MapNestedStringInterface["a"]) require.Nil(t, resp.MapNestedStringInterface["b"]) + require.Equal(t, "42", resp.MapNestedStringInterface["c"]) + require.NotNil(t, resp.MapNestedStringInterface["nested"]) + require.IsType(t, map[string]interface{}{}, resp.MapNestedStringInterface["nested"]) + require.Equal(t, "31", (resp.MapNestedStringInterface["nested"].(map[string]interface{}))["value"]) }) t.Run("nested nil", func(t *testing.T) { var resp struct { MapNestedStringInterface map[string]interface{} } - err := c.Post(`query { mapNestedStringInterface(in: { map: null }) { a, b } }`, &resp) + err := c.Post(`query { mapNestedStringInterface(in: { map: null }) { a, b, c, nested { value } } }`, &resp) require.NoError(t, err) require.Nil(t, resp.MapNestedStringInterface) }) } + +func validateMapItemsType(t *testing.T, in map[string]interface{}) { + for k, v := range in { + switch k { + case "a": + require.IsType(t, "", v) + case "b": + require.IsType(t, new(int), v) + case "c": + require.IsType(t, new(CustomScalar), v) + case "nested": + require.IsType(t, new(MapNested), v) + default: + require.Failf(t, "unexpected key in map", "key %q was not expected in map", k) + } + } +} diff --git a/codegen/type.gotpl b/codegen/type.gotpl index 5cbd737c77..99ad9e0006 100644 --- a/codegen/type.gotpl +++ b/codegen/type.gotpl @@ -59,8 +59,6 @@ {{- else}} return res, graphql.ErrorOnPath(ctx, err) {{- end }} - {{- else if eq ($type.GO | ref) "map[string]interface{}" }} - return v.(map[string]interface{}), nil {{- else if $type.IsMarshaler }} {{- if and $type.IsNilable $type.Elem }} var res = new({{ $type.Elem.GO | ref }}) @@ -75,7 +73,7 @@ return res, graphql.ErrorOnPath(ctx, err) {{- else }} res, err := ec.unmarshalInput{{ $type.GQL.Name }}(ctx, v) - {{- if and $type.IsNilable (not $type.PointersInUmarshalInput) }} + {{- if and $type.IsNilable (not $type.IsMap) (not $type.PointersInUmarshalInput) }} return &res, graphql.ErrorOnPath(ctx, err) {{- else if and (not $type.IsNilable) $type.PointersInUmarshalInput }} return *res, graphql.ErrorOnPath(ctx, err) diff --git a/docs/content/reference/changesets.md b/docs/content/reference/changesets.md index 329206ba5e..513eb67817 100644 --- a/docs/content/reference/changesets.md +++ b/docs/content/reference/changesets.md @@ -13,7 +13,7 @@ type Mutation { updateUser(id: ID!, changes: UserChanges!): User } -type UserChanges { +input UserChanges { name: String email: String } @@ -36,6 +36,9 @@ func (r *mutationResolver) UpdateUser(ctx context.Context, id int, changes map[s } ``` +Please note that map values are automatically coerced to the types defined in the schema. +This means that optional, nested inputs or scalars will conform to their expected types. + We often use the mapstructure library to directly apply these changesets directly to the object using reflection: ```go diff --git a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go index 2b0888d10b..c0c9b89f85 100644 --- a/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go +++ b/plugin/resolvergen/testdata/filetemplate/out/schema.custom.go @@ -2,7 +2,7 @@ package customresolver // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" @@ -36,9 +36,9 @@ type resolverCustomResolverType struct{ *CustomResolverType } // !!! WARNING !!! // The code below was going to be deleted when updating resolvers. It has been copied here so you have // one last chance to move it out of harms way if you want. There are two reasons this happens: -// - When renaming or deleting a resolver the old code will be put in here. You can safely delete -// it when you're done. -// - You have helper methods in this file. Move them out to keep these resolver files clean. +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. func AUserHelperFunction() { // AUserHelperFunction implementation } diff --git a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go index 87d3aab316..c2b7384156 100644 --- a/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/followschema/out/schema.resolvers.go @@ -2,7 +2,7 @@ package customresolver // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" @@ -36,9 +36,9 @@ type resolverCustomResolverType struct{ *CustomResolverType } // !!! WARNING !!! // The code below was going to be deleted when updating resolvers. It has been copied here so you have // one last chance to move it out of harms way if you want. There are two reasons this happens: -// - When renaming or deleting a resolver the old code will be put in here. You can safely delete -// it when you're done. -// - You have helper methods in this file. Move them out to keep these resolver files clean. +// - When renaming or deleting a resolver the old code will be put in here. You can safely delete +// it when you're done. +// - You have helper methods in this file. Move them out to keep these resolver files clean. func AUserHelperFunction() { // AUserHelperFunction implementation } diff --git a/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go b/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go index 7ae5c3e1ed..349f77fc44 100644 --- a/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/omit_template_comment/out/schema.resolvers.go @@ -2,7 +2,7 @@ package out // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" diff --git a/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go b/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go index 4c5eded0f2..27f0503602 100644 --- a/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go +++ b/plugin/resolvergen/testdata/resolvertemplate/out/schema.resolvers.go @@ -2,7 +2,7 @@ package out // 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.38-dev +// Code generated by github.com/99designs/gqlgen version v0.17.39-dev import ( "context" From c5ad14bf6c4203cefee7888e35e1f07e3a46e77a Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Tue, 24 Oct 2023 09:35:41 -0400 Subject: [PATCH 53/54] release v0.17.40 --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index c81e4e09aa..e2aeb22d28 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index ebeb0981e3..2fbab195be 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index b6ddad1875..3aaeabb1bb 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 3d68de26fb..1f0543cb88 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index 81d1e1e81d..1a6fa95050 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index 7e4597385d..2289268919 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index 1954ecd78f..8ed0511e93 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 26bd75998c..9855882191 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index ce04d6a10c..5bbad739ba 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" diff --git a/graphql/version.go b/graphql/version.go index cf8db2360e..907310219c 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.39-dev" +const Version = "v0.17.40" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index 926757a1df..821b1bf5bc 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.39-dev +// Code generated by github.com/99designs/gqlgen version v0.17.40 import ( "context" From 917407005eb4198aa43875984fb77caeaa7fca36 Mon Sep 17 00:00:00 2001 From: Steve Coffman Date: Tue, 24 Oct 2023 09:36:22 -0400 Subject: [PATCH 54/54] v0.17.40 postrelease bump --- _examples/config/schema.resolvers.go | 2 +- _examples/config/todo.resolvers.go | 2 +- _examples/config/user.resolvers.go | 2 +- _examples/federation/accounts/graph/entity.resolvers.go | 2 +- _examples/federation/accounts/graph/schema.resolvers.go | 2 +- _examples/federation/products/graph/entity.resolvers.go | 2 +- _examples/federation/products/graph/schema.resolvers.go | 2 +- _examples/federation/reviews/graph/entity.resolvers.go | 2 +- _examples/federation/reviews/graph/schema.resolvers.go | 2 +- graphql/version.go | 2 +- plugin/federation/testdata/entityresolver/entity.resolvers.go | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/_examples/config/schema.resolvers.go b/_examples/config/schema.resolvers.go index e2aeb22d28..c783ab751e 100644 --- a/_examples/config/schema.resolvers.go +++ b/_examples/config/schema.resolvers.go @@ -2,7 +2,7 @@ package config // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/config/todo.resolvers.go b/_examples/config/todo.resolvers.go index 2fbab195be..57ca050c8e 100644 --- a/_examples/config/todo.resolvers.go +++ b/_examples/config/todo.resolvers.go @@ -2,7 +2,7 @@ package config // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/config/user.resolvers.go b/_examples/config/user.resolvers.go index 3aaeabb1bb..05a4deb48c 100644 --- a/_examples/config/user.resolvers.go +++ b/_examples/config/user.resolvers.go @@ -2,7 +2,7 @@ package config // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/federation/accounts/graph/entity.resolvers.go b/_examples/federation/accounts/graph/entity.resolvers.go index 1f0543cb88..31b2cad602 100644 --- a/_examples/federation/accounts/graph/entity.resolvers.go +++ b/_examples/federation/accounts/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/federation/accounts/graph/schema.resolvers.go b/_examples/federation/accounts/graph/schema.resolvers.go index 1a6fa95050..a3364c1207 100644 --- a/_examples/federation/accounts/graph/schema.resolvers.go +++ b/_examples/federation/accounts/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/federation/products/graph/entity.resolvers.go b/_examples/federation/products/graph/entity.resolvers.go index 2289268919..840d32321a 100644 --- a/_examples/federation/products/graph/entity.resolvers.go +++ b/_examples/federation/products/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/federation/products/graph/schema.resolvers.go b/_examples/federation/products/graph/schema.resolvers.go index 8ed0511e93..87d62e225c 100644 --- a/_examples/federation/products/graph/schema.resolvers.go +++ b/_examples/federation/products/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/federation/reviews/graph/entity.resolvers.go b/_examples/federation/reviews/graph/entity.resolvers.go index 9855882191..08102f8a30 100644 --- a/_examples/federation/reviews/graph/entity.resolvers.go +++ b/_examples/federation/reviews/graph/entity.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/_examples/federation/reviews/graph/schema.resolvers.go b/_examples/federation/reviews/graph/schema.resolvers.go index 5bbad739ba..4900e4d8e2 100644 --- a/_examples/federation/reviews/graph/schema.resolvers.go +++ b/_examples/federation/reviews/graph/schema.resolvers.go @@ -2,7 +2,7 @@ package graph // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context" diff --git a/graphql/version.go b/graphql/version.go index 907310219c..92812f7acc 100644 --- a/graphql/version.go +++ b/graphql/version.go @@ -1,3 +1,3 @@ package graphql -const Version = "v0.17.40" +const Version = "v0.17.40-dev" diff --git a/plugin/federation/testdata/entityresolver/entity.resolvers.go b/plugin/federation/testdata/entityresolver/entity.resolvers.go index 821b1bf5bc..bc1e3c0d78 100644 --- a/plugin/federation/testdata/entityresolver/entity.resolvers.go +++ b/plugin/federation/testdata/entityresolver/entity.resolvers.go @@ -2,7 +2,7 @@ package entityresolver // 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.40 +// Code generated by github.com/99designs/gqlgen version v0.17.40-dev import ( "context"