From a30eecc7614c4e9de7d8b7ab02da6bf7806343cf Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 01:34:54 +0700 Subject: [PATCH 01/23] fix: expose functions for the plugin --- entgql/extension.go | 6 +++--- entgql/template.go | 16 ++++++++-------- entgql/template_test.go | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/entgql/extension.go b/entgql/extension.go index 70ee2d681..0f9630287 100644 --- a/entgql/extension.go +++ b/entgql/extension.go @@ -322,7 +322,7 @@ func (e *Extension) genWhereInputs() gen.Hook { } inputs := make(map[string]*ast.InputObjectDefinition) return gen.GenerateFunc(func(g *gen.Graph) error { - nodes, err := filterNodes(g.Nodes) + nodes, err := FilterNodes(g.Nodes) if err != nil { return err } @@ -416,7 +416,7 @@ func (e *Extension) whereType(t *gen.Type) (string, *ast.InputObjectDefinition, }), })) } - fields, err := filterFields(append(t.Fields, t.ID)) + fields, err := FilterFields(append(t.Fields, t.ID)) if err != nil { return "", nil, err } @@ -434,7 +434,7 @@ func (e *Extension) whereType(t *gen.Type) (string, *ast.InputObjectDefinition, input.Fields = append(input.Fields, fd) } } - edges, err := filterEdges(t.Edges) + edges, err := FilterEdges(t.Edges) if err != nil { return "", nil, err } diff --git a/entgql/template.go b/entgql/template.go index a1c9a8aea..f9fc8e0e8 100644 --- a/entgql/template.go +++ b/entgql/template.go @@ -65,10 +65,10 @@ var ( // TemplateFuncs contains the extra template functions used by entgql. TemplateFuncs = template.FuncMap{ "fieldCollections": fieldCollections, - "filterEdges": filterEdges, - "filterFields": filterFields, - "filterNodes": filterNodes, - "findIDType": findIDType, + "filterEdges": FilterEdges, + "filterFields": FilterFields, + "filterNodes": FilterNodes, + "findIDType": FindIDType, } //go:embed template/* @@ -81,7 +81,7 @@ func parseT(path string) *gen.Template { ParseFS(templates, path)) } -func findIDType(nodes []*gen.Type, defaultType *field.TypeInfo) (*field.TypeInfo, error) { +func FindIDType(nodes []*gen.Type, defaultType *field.TypeInfo) (*field.TypeInfo, error) { t := defaultType if len(nodes) > 0 { t = nodes[0].ID.Type @@ -132,7 +132,7 @@ func fieldCollections(edges []*gen.Edge) (map[string]fieldCollection, error) { return result, nil } -func filterNodes(nodes []*gen.Type) ([]*gen.Type, error) { +func FilterNodes(nodes []*gen.Type) ([]*gen.Type, error) { var filteredNodes []*gen.Type for _, n := range nodes { ant := &Annotation{} @@ -149,7 +149,7 @@ func filterNodes(nodes []*gen.Type) ([]*gen.Type, error) { return filteredNodes, nil } -func filterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { +func FilterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { var filteredEdges []*gen.Edge for _, e := range edges { ant := &Annotation{} @@ -175,7 +175,7 @@ func filterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { return filteredEdges, nil } -func filterFields(fields []*gen.Field) ([]*gen.Field, error) { +func FilterFields(fields []*gen.Field) ([]*gen.Field, error) { var filteredFields []*gen.Field for _, f := range fields { ant := &Annotation{} diff --git a/entgql/template_test.go b/entgql/template_test.go index 234efb390..6aa8a5a89 100644 --- a/entgql/template_test.go +++ b/entgql/template_test.go @@ -24,7 +24,7 @@ import ( var annotationName = Annotation{}.Name() func TestFilterNodes(t *testing.T) { - nodes, err := filterNodes([]*gen.Type{ + nodes, err := FilterNodes([]*gen.Type{ { Name: "Type1", Annotations: map[string]interface{}{ @@ -58,7 +58,7 @@ func TestFilterNodes(t *testing.T) { } func TestFilterEdges(t *testing.T) { - edges, err := filterEdges([]*gen.Edge{ + edges, err := FilterEdges([]*gen.Edge{ { Name: "Edge1", Type: &gen.Type{}, @@ -178,7 +178,7 @@ func TestFieldCollections(t *testing.T) { } func TestFilterFields(t *testing.T) { - fields, err := filterFields([]*gen.Field{ + fields, err := FilterFields([]*gen.Field{ { Name: "Field1", Annotations: map[string]interface{}{ From 72531ccfd637025f213697cc54a40bb3dce7774e Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 18:44:20 +0000 Subject: [PATCH 02/23] feat: created the noop plugin --- entgql/plugin/plugin.go | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 entgql/plugin/plugin.go diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go new file mode 100644 index 000000000..1e67e720b --- /dev/null +++ b/entgql/plugin/plugin.go @@ -0,0 +1,68 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "entgo.io/contrib/entgql" + "entgo.io/ent/entc/gen" + "github.com/99designs/gqlgen/plugin" + "github.com/vektah/gqlparser/v2/ast" +) + +type ( + // EntGQL is a plugin that generates GQL schema from the Ent's Graph + EntGQL struct { + graph *gen.Graph + nodes []*gen.Type + } + + // EntGQLPluginOption is a option for the EntGQL plugin + EntGQLPluginOption func(*EntGQL) error +) + +var ( + _ plugin.Plugin = (*EntGQL)(nil) + _ plugin.EarlySourceInjector = (*EntGQL)(nil) +) + +// NewEntGQLPlugin creates a new EntGQL plugin +func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLPluginOption) (*EntGQL, error) { + nodes, err := entgql.FilterNodes(graph.Nodes) + if err != nil { + return nil, err + } + + e := &EntGQL{ + graph: graph, + nodes: nodes, + } + for _, opt := range opts { + if err = opt(e); err != nil { + return nil, err + } + } + + return e, nil +} + +// Name implements the Plugin interface. +func (*EntGQL) Name() string { + return "entgql" +} + +// InjectSourceEarly implements the EarlySourceInjector interface. +func (e *EntGQL) InjectSourceEarly() *ast.Source { + return nil +} From d8355b5c810d95f8672829222151a7dfde007790 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 20:33:58 +0000 Subject: [PATCH 03/23] chore: added todoplugin for setup tests --- entgql/internal/todoplugin/cmd/entgqlgen.go | 93 + entgql/internal/todoplugin/ent/category.go | 198 + .../todoplugin/ent/category/category.go | 120 + .../internal/todoplugin/ent/category/where.go | 647 +++ .../todoplugin/ent/category_create.go | 370 ++ .../todoplugin/ent/category_delete.go | 125 + .../internal/todoplugin/ent/category_query.go | 1006 ++++ .../todoplugin/ent/category_update.go | 818 +++ entgql/internal/todoplugin/ent/client.go | 471 ++ entgql/internal/todoplugin/ent/config.go | 75 + entgql/internal/todoplugin/ent/context.go | 47 + entgql/internal/todoplugin/ent/ent.go | 277 + entgql/internal/todoplugin/ent/entc.go | 12 + .../todoplugin/ent/enttest/enttest.go | 92 + .../internal/todoplugin/ent/gql_collection.go | 71 + entgql/internal/todoplugin/ent/gql_edge.go | 43 + entgql/internal/todoplugin/ent/gql_node.go | 510 ++ .../internal/todoplugin/ent/gql_pagination.go | 1086 ++++ .../todoplugin/ent/gql_transaction.go | 44 + .../todoplugin/ent/gql_where_input.go | 925 +++ entgql/internal/todoplugin/ent/hook/hook.go | 244 + .../todoplugin/ent/migrate/migrate.go | 85 + .../internal/todoplugin/ent/migrate/schema.go | 97 + entgql/internal/todoplugin/ent/mutation.go | 2130 +++++++ .../todoplugin/ent/pagination_test.go | 73 + .../todoplugin/ent/predicate/predicate.go | 30 + entgql/internal/todoplugin/ent/role/role.go | 40 + entgql/internal/todoplugin/ent/runtime.go | 51 + .../todoplugin/ent/runtime/runtime.go | 24 + .../todoplugin/ent/schema/category.go | 87 + .../ent/schema/durationgql/durationgql.go | 48 + .../ent/schema/schematype/schematype.go | 40 + entgql/internal/todoplugin/ent/schema/todo.go | 84 + entgql/internal/todoplugin/ent/schema/user.go | 47 + entgql/internal/todoplugin/ent/todo.go | 223 + entgql/internal/todoplugin/ent/todo/todo.go | 181 + entgql/internal/todoplugin/ent/todo/where.go | 576 ++ entgql/internal/todoplugin/ent/todo_create.go | 433 ++ entgql/internal/todoplugin/ent/todo_delete.go | 125 + entgql/internal/todoplugin/ent/todo_query.go | 1078 ++++ entgql/internal/todoplugin/ent/todo_update.go | 769 +++ entgql/internal/todoplugin/ent/tx.go | 230 + entgql/internal/todoplugin/ent/user.go | 147 + entgql/internal/todoplugin/ent/user/user.go | 77 + entgql/internal/todoplugin/ent/user/where.go | 480 ++ entgql/internal/todoplugin/ent/user_create.go | 292 + entgql/internal/todoplugin/ent/user_delete.go | 125 + entgql/internal/todoplugin/ent/user_query.go | 934 +++ entgql/internal/todoplugin/ent/user_update.go | 447 ++ entgql/internal/todoplugin/gen.go | 19 + entgql/internal/todoplugin/generated.go | 5136 +++++++++++++++++ entgql/internal/todoplugin/gqlgen.yml | 46 + entgql/internal/todoplugin/models_gen.go | 15 + entgql/internal/todoplugin/resolver.go | 37 + entgql/internal/todoplugin/server/server.go | 71 + entgql/internal/todoplugin/todo.graphql | 117 + entgql/internal/todoplugin/todo.resolvers.go | 87 + entgql/internal/todoplugin/todo_test.go | 803 +++ 58 files changed, 22558 insertions(+) create mode 100644 entgql/internal/todoplugin/cmd/entgqlgen.go create mode 100644 entgql/internal/todoplugin/ent/category.go create mode 100644 entgql/internal/todoplugin/ent/category/category.go create mode 100644 entgql/internal/todoplugin/ent/category/where.go create mode 100644 entgql/internal/todoplugin/ent/category_create.go create mode 100644 entgql/internal/todoplugin/ent/category_delete.go create mode 100644 entgql/internal/todoplugin/ent/category_query.go create mode 100644 entgql/internal/todoplugin/ent/category_update.go create mode 100644 entgql/internal/todoplugin/ent/client.go create mode 100644 entgql/internal/todoplugin/ent/config.go create mode 100644 entgql/internal/todoplugin/ent/context.go create mode 100644 entgql/internal/todoplugin/ent/ent.go create mode 100644 entgql/internal/todoplugin/ent/entc.go create mode 100644 entgql/internal/todoplugin/ent/enttest/enttest.go create mode 100644 entgql/internal/todoplugin/ent/gql_collection.go create mode 100644 entgql/internal/todoplugin/ent/gql_edge.go create mode 100644 entgql/internal/todoplugin/ent/gql_node.go create mode 100644 entgql/internal/todoplugin/ent/gql_pagination.go create mode 100644 entgql/internal/todoplugin/ent/gql_transaction.go create mode 100644 entgql/internal/todoplugin/ent/gql_where_input.go create mode 100644 entgql/internal/todoplugin/ent/hook/hook.go create mode 100644 entgql/internal/todoplugin/ent/migrate/migrate.go create mode 100644 entgql/internal/todoplugin/ent/migrate/schema.go create mode 100644 entgql/internal/todoplugin/ent/mutation.go create mode 100644 entgql/internal/todoplugin/ent/pagination_test.go create mode 100644 entgql/internal/todoplugin/ent/predicate/predicate.go create mode 100644 entgql/internal/todoplugin/ent/role/role.go create mode 100644 entgql/internal/todoplugin/ent/runtime.go create mode 100644 entgql/internal/todoplugin/ent/runtime/runtime.go create mode 100644 entgql/internal/todoplugin/ent/schema/category.go create mode 100644 entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go create mode 100644 entgql/internal/todoplugin/ent/schema/schematype/schematype.go create mode 100644 entgql/internal/todoplugin/ent/schema/todo.go create mode 100644 entgql/internal/todoplugin/ent/schema/user.go create mode 100644 entgql/internal/todoplugin/ent/todo.go create mode 100644 entgql/internal/todoplugin/ent/todo/todo.go create mode 100644 entgql/internal/todoplugin/ent/todo/where.go create mode 100644 entgql/internal/todoplugin/ent/todo_create.go create mode 100644 entgql/internal/todoplugin/ent/todo_delete.go create mode 100644 entgql/internal/todoplugin/ent/todo_query.go create mode 100644 entgql/internal/todoplugin/ent/todo_update.go create mode 100644 entgql/internal/todoplugin/ent/tx.go create mode 100644 entgql/internal/todoplugin/ent/user.go create mode 100644 entgql/internal/todoplugin/ent/user/user.go create mode 100644 entgql/internal/todoplugin/ent/user/where.go create mode 100644 entgql/internal/todoplugin/ent/user_create.go create mode 100644 entgql/internal/todoplugin/ent/user_delete.go create mode 100644 entgql/internal/todoplugin/ent/user_query.go create mode 100644 entgql/internal/todoplugin/ent/user_update.go create mode 100644 entgql/internal/todoplugin/gen.go create mode 100644 entgql/internal/todoplugin/generated.go create mode 100644 entgql/internal/todoplugin/gqlgen.yml create mode 100644 entgql/internal/todoplugin/models_gen.go create mode 100644 entgql/internal/todoplugin/resolver.go create mode 100644 entgql/internal/todoplugin/server/server.go create mode 100644 entgql/internal/todoplugin/todo.graphql create mode 100644 entgql/internal/todoplugin/todo.resolvers.go create mode 100644 entgql/internal/todoplugin/todo_test.go diff --git a/entgql/internal/todoplugin/cmd/entgqlgen.go b/entgql/internal/todoplugin/cmd/entgqlgen.go new file mode 100644 index 000000000..f80355a9e --- /dev/null +++ b/entgql/internal/todoplugin/cmd/entgqlgen.go @@ -0,0 +1,93 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "fmt" + "log" + "os" + + "entgo.io/contrib/entgql" + "entgo.io/contrib/entgql/plugin" + "entgo.io/ent/entc" + "entgo.io/ent/entc/gen" + "github.com/99designs/gqlgen/api" + "github.com/99designs/gqlgen/codegen/config" +) + +func main() { + var ( + schemaPath = flag.String("path", "", "path to schema directory") + ) + flag.Parse() + if *schemaPath == "" { + log.Fatal("entgqlgen: must specify schema path. use entgqlgen -path ./ent/schema") + } + + graph, err := entc.LoadGraph(*schemaPath, &gen.Config{}) + if err != nil { + log.Fatalf("entgqlgen: failed loading ent graph: %v", err) + } + + cfg, err := config.LoadConfigFromDefaultLocations() + if err != nil { + fmt.Fprintln(os.Stderr, "failed to load config", err.Error()) + os.Exit(2) + } + + entgqlPlugin, err := plugin.NewEntGQLPlugin(graph) + if err != nil { + log.Fatalf("creating entgql plugin: %v", err) + } + + ex, err := entgql.NewExtension() + if err != nil { + log.Fatalf("creating entgql extension: %v", err) + } + err = entc.Generate(*schemaPath, &gen.Config{ + Header: ` + // Copyright 2019-present Facebook + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + // + // Code generated by entc, DO NOT EDIT. + `, + }, entc.Extensions(ex)) + if err != nil { + log.Fatalf("running ent codegen: %v", err) + } + if err != nil { + fmt.Fprintln(os.Stderr, "failed to create entgql plugin", err.Error()) + os.Exit(2) + } + err = api.Generate(cfg, + api.PrependPlugin(entgqlPlugin), + ) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(3) + } +} diff --git a/entgql/internal/todoplugin/ent/category.go b/entgql/internal/todoplugin/ent/category.go new file mode 100644 index 000000000..a6d67ffb3 --- /dev/null +++ b/entgql/internal/todoplugin/ent/category.go @@ -0,0 +1,198 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/ent/dialect/sql" +) + +// Category is the model entity for the Category schema. +type Category struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Text holds the value of the "text" field. + Text string `json:"text,omitempty"` + // Status holds the value of the "status" field. + Status category.Status `json:"status,omitempty"` + // Config holds the value of the "config" field. + Config *schematype.CategoryConfig `json:"config,omitempty"` + // Duration holds the value of the "duration" field. + Duration time.Duration `json:"duration,omitempty"` + // Count holds the value of the "count" field. + Count uint64 `json:"count,omitempty"` + // Strings holds the value of the "strings" field. + Strings []string `json:"strings,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the CategoryQuery when eager-loading is set. + Edges CategoryEdges `json:"edges"` +} + +// CategoryEdges holds the relations/edges for other nodes in the graph. +type CategoryEdges struct { + // Todos holds the value of the todos edge. + Todos []*Todo `json:"todos,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool +} + +// TodosOrErr returns the Todos value or an error if the edge +// was not loaded in eager-loading. +func (e CategoryEdges) TodosOrErr() ([]*Todo, error) { + if e.loadedTypes[0] { + return e.Todos, nil + } + return nil, &NotLoadedError{edge: "todos"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Category) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case category.FieldStrings: + values[i] = new([]byte) + case category.FieldConfig: + values[i] = new(schematype.CategoryConfig) + case category.FieldID, category.FieldDuration, category.FieldCount: + values[i] = new(sql.NullInt64) + case category.FieldText, category.FieldStatus: + values[i] = new(sql.NullString) + default: + return nil, fmt.Errorf("unexpected column %q for type Category", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Category fields. +func (c *Category) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case category.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + c.ID = int(value.Int64) + case category.FieldText: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field text", values[i]) + } else if value.Valid { + c.Text = value.String + } + case category.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + c.Status = category.Status(value.String) + } + case category.FieldConfig: + if value, ok := values[i].(*schematype.CategoryConfig); !ok { + return fmt.Errorf("unexpected type %T for field config", values[i]) + } else if value != nil { + c.Config = value + } + case category.FieldDuration: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field duration", values[i]) + } else if value.Valid { + c.Duration = time.Duration(value.Int64) + } + case category.FieldCount: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field count", values[i]) + } else if value.Valid { + c.Count = uint64(value.Int64) + } + case category.FieldStrings: + if value, ok := values[i].(*[]byte); !ok { + return fmt.Errorf("unexpected type %T for field strings", values[i]) + } else if value != nil && len(*value) > 0 { + if err := json.Unmarshal(*value, &c.Strings); err != nil { + return fmt.Errorf("unmarshal field strings: %w", err) + } + } + } + } + return nil +} + +// QueryTodos queries the "todos" edge of the Category entity. +func (c *Category) QueryTodos() *TodoQuery { + return (&CategoryClient{config: c.config}).QueryTodos(c) +} + +// Update returns a builder for updating this Category. +// Note that you need to call Category.Unwrap() before calling this method if this Category +// was returned from a transaction, and the transaction was committed or rolled back. +func (c *Category) Update() *CategoryUpdateOne { + return (&CategoryClient{config: c.config}).UpdateOne(c) +} + +// Unwrap unwraps the Category entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (c *Category) Unwrap() *Category { + tx, ok := c.config.driver.(*txDriver) + if !ok { + panic("ent: Category is not a transactional entity") + } + c.config.driver = tx.drv + return c +} + +// String implements the fmt.Stringer. +func (c *Category) String() string { + var builder strings.Builder + builder.WriteString("Category(") + builder.WriteString(fmt.Sprintf("id=%v", c.ID)) + builder.WriteString(", text=") + builder.WriteString(c.Text) + builder.WriteString(", status=") + builder.WriteString(fmt.Sprintf("%v", c.Status)) + builder.WriteString(", config=") + builder.WriteString(fmt.Sprintf("%v", c.Config)) + builder.WriteString(", duration=") + builder.WriteString(fmt.Sprintf("%v", c.Duration)) + builder.WriteString(", count=") + builder.WriteString(fmt.Sprintf("%v", c.Count)) + builder.WriteString(", strings=") + builder.WriteString(fmt.Sprintf("%v", c.Strings)) + builder.WriteByte(')') + return builder.String() +} + +// Categories is a parsable slice of Category. +type Categories []*Category + +func (c Categories) config(cfg config) { + for _i := range c { + c[_i].config = cfg + } +} diff --git a/entgql/internal/todoplugin/ent/category/category.go b/entgql/internal/todoplugin/ent/category/category.go new file mode 100644 index 000000000..12f9be698 --- /dev/null +++ b/entgql/internal/todoplugin/ent/category/category.go @@ -0,0 +1,120 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package category + +import ( + "fmt" + "io" + "strconv" +) + +const ( + // Label holds the string label denoting the category type in the database. + Label = "category" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldText holds the string denoting the text field in the database. + FieldText = "text" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldConfig holds the string denoting the config field in the database. + FieldConfig = "config" + // FieldDuration holds the string denoting the duration field in the database. + FieldDuration = "duration" + // FieldCount holds the string denoting the count field in the database. + FieldCount = "count" + // FieldStrings holds the string denoting the strings field in the database. + FieldStrings = "strings" + // EdgeTodos holds the string denoting the todos edge name in mutations. + EdgeTodos = "todos" + // Table holds the table name of the category in the database. + Table = "categories" + // TodosTable is the table that holds the todos relation/edge. + TodosTable = "todos" + // TodosInverseTable is the table name for the Todo entity. + // It exists in this package in order to avoid circular dependency with the "todo" package. + TodosInverseTable = "todos" + // TodosColumn is the table column denoting the todos relation/edge. + TodosColumn = "category_todos" +) + +// Columns holds all SQL columns for category fields. +var Columns = []string{ + FieldID, + FieldText, + FieldStatus, + FieldConfig, + FieldDuration, + FieldCount, + FieldStrings, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +var ( + // TextValidator is a validator for the "text" field. It is called by the builders before save. + TextValidator func(string) error +) + +// Status defines the type for the "status" enum field. +type Status string + +// Status values. +const ( + StatusEnabled Status = "ENABLED" + StatusDisabled Status = "DISABLED" +) + +func (s Status) String() string { + return string(s) +} + +// StatusValidator is a validator for the "status" field enum values. It is called by the builders before save. +func StatusValidator(s Status) error { + switch s { + case StatusEnabled, StatusDisabled: + return nil + default: + return fmt.Errorf("category: invalid enum value for status field: %q", s) + } +} + +// MarshalGQL implements graphql.Marshaler interface. +func (e Status) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(e.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (e *Status) UnmarshalGQL(val interface{}) error { + str, ok := val.(string) + if !ok { + return fmt.Errorf("enum %T must be a string", val) + } + *e = Status(str) + if err := StatusValidator(*e); err != nil { + return fmt.Errorf("%s is not a valid Status", str) + } + return nil +} diff --git a/entgql/internal/todoplugin/ent/category/where.go b/entgql/internal/todoplugin/ent/category/where.go new file mode 100644 index 000000000..80739f7c0 --- /dev/null +++ b/entgql/internal/todoplugin/ent/category/where.go @@ -0,0 +1,647 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package category + +import ( + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// Text applies equality check predicate on the "text" field. It's identical to TextEQ. +func Text(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldText), v)) + }) +} + +// Config applies equality check predicate on the "config" field. It's identical to ConfigEQ. +func Config(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldConfig), v)) + }) +} + +// Duration applies equality check predicate on the "duration" field. It's identical to DurationEQ. +func Duration(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldDuration), vc)) + }) +} + +// Count applies equality check predicate on the "count" field. It's identical to CountEQ. +func Count(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCount), v)) + }) +} + +// TextEQ applies the EQ predicate on the "text" field. +func TextEQ(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldText), v)) + }) +} + +// TextNEQ applies the NEQ predicate on the "text" field. +func TextNEQ(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldText), v)) + }) +} + +// TextIn applies the In predicate on the "text" field. +func TextIn(vs ...string) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldText), v...)) + }) +} + +// TextNotIn applies the NotIn predicate on the "text" field. +func TextNotIn(vs ...string) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldText), v...)) + }) +} + +// TextGT applies the GT predicate on the "text" field. +func TextGT(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldText), v)) + }) +} + +// TextGTE applies the GTE predicate on the "text" field. +func TextGTE(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldText), v)) + }) +} + +// TextLT applies the LT predicate on the "text" field. +func TextLT(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldText), v)) + }) +} + +// TextLTE applies the LTE predicate on the "text" field. +func TextLTE(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldText), v)) + }) +} + +// TextContains applies the Contains predicate on the "text" field. +func TextContains(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldText), v)) + }) +} + +// TextHasPrefix applies the HasPrefix predicate on the "text" field. +func TextHasPrefix(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldText), v)) + }) +} + +// TextHasSuffix applies the HasSuffix predicate on the "text" field. +func TextHasSuffix(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldText), v)) + }) +} + +// TextEqualFold applies the EqualFold predicate on the "text" field. +func TextEqualFold(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldText), v)) + }) +} + +// TextContainsFold applies the ContainsFold predicate on the "text" field. +func TextContainsFold(v string) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldText), v)) + }) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v Status) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldStatus), v)) + }) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v Status) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldStatus), v)) + }) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...Status) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldStatus), v...)) + }) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...Status) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldStatus), v...)) + }) +} + +// ConfigEQ applies the EQ predicate on the "config" field. +func ConfigEQ(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldConfig), v)) + }) +} + +// ConfigNEQ applies the NEQ predicate on the "config" field. +func ConfigNEQ(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldConfig), v)) + }) +} + +// ConfigIn applies the In predicate on the "config" field. +func ConfigIn(vs ...*schematype.CategoryConfig) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldConfig), v...)) + }) +} + +// ConfigNotIn applies the NotIn predicate on the "config" field. +func ConfigNotIn(vs ...*schematype.CategoryConfig) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldConfig), v...)) + }) +} + +// ConfigGT applies the GT predicate on the "config" field. +func ConfigGT(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldConfig), v)) + }) +} + +// ConfigGTE applies the GTE predicate on the "config" field. +func ConfigGTE(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldConfig), v)) + }) +} + +// ConfigLT applies the LT predicate on the "config" field. +func ConfigLT(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldConfig), v)) + }) +} + +// ConfigLTE applies the LTE predicate on the "config" field. +func ConfigLTE(v *schematype.CategoryConfig) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldConfig), v)) + }) +} + +// ConfigIsNil applies the IsNil predicate on the "config" field. +func ConfigIsNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldConfig))) + }) +} + +// ConfigNotNil applies the NotNil predicate on the "config" field. +func ConfigNotNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldConfig))) + }) +} + +// DurationEQ applies the EQ predicate on the "duration" field. +func DurationEQ(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldDuration), vc)) + }) +} + +// DurationNEQ applies the NEQ predicate on the "duration" field. +func DurationNEQ(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldDuration), vc)) + }) +} + +// DurationIn applies the In predicate on the "duration" field. +func DurationIn(vs ...time.Duration) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = int64(vs[i]) + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldDuration), v...)) + }) +} + +// DurationNotIn applies the NotIn predicate on the "duration" field. +func DurationNotIn(vs ...time.Duration) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = int64(vs[i]) + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldDuration), v...)) + }) +} + +// DurationGT applies the GT predicate on the "duration" field. +func DurationGT(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldDuration), vc)) + }) +} + +// DurationGTE applies the GTE predicate on the "duration" field. +func DurationGTE(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldDuration), vc)) + }) +} + +// DurationLT applies the LT predicate on the "duration" field. +func DurationLT(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldDuration), vc)) + }) +} + +// DurationLTE applies the LTE predicate on the "duration" field. +func DurationLTE(v time.Duration) predicate.Category { + vc := int64(v) + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldDuration), vc)) + }) +} + +// DurationIsNil applies the IsNil predicate on the "duration" field. +func DurationIsNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldDuration))) + }) +} + +// DurationNotNil applies the NotNil predicate on the "duration" field. +func DurationNotNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldDuration))) + }) +} + +// CountEQ applies the EQ predicate on the "count" field. +func CountEQ(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCount), v)) + }) +} + +// CountNEQ applies the NEQ predicate on the "count" field. +func CountNEQ(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldCount), v)) + }) +} + +// CountIn applies the In predicate on the "count" field. +func CountIn(vs ...uint64) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldCount), v...)) + }) +} + +// CountNotIn applies the NotIn predicate on the "count" field. +func CountNotIn(vs ...uint64) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldCount), v...)) + }) +} + +// CountGT applies the GT predicate on the "count" field. +func CountGT(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldCount), v)) + }) +} + +// CountGTE applies the GTE predicate on the "count" field. +func CountGTE(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldCount), v)) + }) +} + +// CountLT applies the LT predicate on the "count" field. +func CountLT(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldCount), v)) + }) +} + +// CountLTE applies the LTE predicate on the "count" field. +func CountLTE(v uint64) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldCount), v)) + }) +} + +// CountIsNil applies the IsNil predicate on the "count" field. +func CountIsNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldCount))) + }) +} + +// CountNotNil applies the NotNil predicate on the "count" field. +func CountNotNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldCount))) + }) +} + +// StringsIsNil applies the IsNil predicate on the "strings" field. +func StringsIsNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldStrings))) + }) +} + +// StringsNotNil applies the NotNil predicate on the "strings" field. +func StringsNotNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldStrings))) + }) +} + +// HasTodos applies the HasEdge predicate on the "todos" edge. +func HasTodos() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TodosTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, TodosTable, TodosColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasTodosWith applies the HasEdge predicate on the "todos" edge with a given conditions (other predicates). +func HasTodosWith(preds ...predicate.Todo) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TodosInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, TodosTable, TodosColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Category) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Category) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Category) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/entgql/internal/todoplugin/ent/category_create.go b/entgql/internal/todoplugin/ent/category_create.go new file mode 100644 index 000000000..a21327a60 --- /dev/null +++ b/entgql/internal/todoplugin/ent/category_create.go @@ -0,0 +1,370 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// CategoryCreate is the builder for creating a Category entity. +type CategoryCreate struct { + config + mutation *CategoryMutation + hooks []Hook +} + +// SetText sets the "text" field. +func (cc *CategoryCreate) SetText(s string) *CategoryCreate { + cc.mutation.SetText(s) + return cc +} + +// SetStatus sets the "status" field. +func (cc *CategoryCreate) SetStatus(c category.Status) *CategoryCreate { + cc.mutation.SetStatus(c) + return cc +} + +// SetConfig sets the "config" field. +func (cc *CategoryCreate) SetConfig(sc *schematype.CategoryConfig) *CategoryCreate { + cc.mutation.SetConfig(sc) + return cc +} + +// SetDuration sets the "duration" field. +func (cc *CategoryCreate) SetDuration(t time.Duration) *CategoryCreate { + cc.mutation.SetDuration(t) + return cc +} + +// SetNillableDuration sets the "duration" field if the given value is not nil. +func (cc *CategoryCreate) SetNillableDuration(t *time.Duration) *CategoryCreate { + if t != nil { + cc.SetDuration(*t) + } + return cc +} + +// SetCount sets the "count" field. +func (cc *CategoryCreate) SetCount(u uint64) *CategoryCreate { + cc.mutation.SetCount(u) + return cc +} + +// SetNillableCount sets the "count" field if the given value is not nil. +func (cc *CategoryCreate) SetNillableCount(u *uint64) *CategoryCreate { + if u != nil { + cc.SetCount(*u) + } + return cc +} + +// SetStrings sets the "strings" field. +func (cc *CategoryCreate) SetStrings(s []string) *CategoryCreate { + cc.mutation.SetStrings(s) + return cc +} + +// AddTodoIDs adds the "todos" edge to the Todo entity by IDs. +func (cc *CategoryCreate) AddTodoIDs(ids ...int) *CategoryCreate { + cc.mutation.AddTodoIDs(ids...) + return cc +} + +// AddTodos adds the "todos" edges to the Todo entity. +func (cc *CategoryCreate) AddTodos(t ...*Todo) *CategoryCreate { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return cc.AddTodoIDs(ids...) +} + +// Mutation returns the CategoryMutation object of the builder. +func (cc *CategoryCreate) Mutation() *CategoryMutation { + return cc.mutation +} + +// Save creates the Category in the database. +func (cc *CategoryCreate) Save(ctx context.Context) (*Category, error) { + var ( + err error + node *Category + ) + if len(cc.hooks) == 0 { + if err = cc.check(); err != nil { + return nil, err + } + node, err = cc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*CategoryMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = cc.check(); err != nil { + return nil, err + } + cc.mutation = mutation + if node, err = cc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(cc.hooks) - 1; i >= 0; i-- { + if cc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = cc.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, cc.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (cc *CategoryCreate) SaveX(ctx context.Context) *Category { + v, err := cc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (cc *CategoryCreate) Exec(ctx context.Context) error { + _, err := cc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cc *CategoryCreate) ExecX(ctx context.Context) { + if err := cc.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (cc *CategoryCreate) check() error { + if _, ok := cc.mutation.Text(); !ok { + return &ValidationError{Name: "text", err: errors.New(`ent: missing required field "Category.text"`)} + } + if v, ok := cc.mutation.Text(); ok { + if err := category.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Category.text": %w`, err)} + } + } + if _, ok := cc.mutation.Status(); !ok { + return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "Category.status"`)} + } + if v, ok := cc.mutation.Status(); ok { + if err := category.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Category.status": %w`, err)} + } + } + return nil +} + +func (cc *CategoryCreate) sqlSave(ctx context.Context) (*Category, error) { + _node, _spec := cc.createSpec() + if err := sqlgraph.CreateNode(ctx, cc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (cc *CategoryCreate) createSpec() (*Category, *sqlgraph.CreateSpec) { + var ( + _node = &Category{config: cc.config} + _spec = &sqlgraph.CreateSpec{ + Table: category.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: category.FieldID, + }, + } + ) + if value, ok := cc.mutation.Text(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: category.FieldText, + }) + _node.Text = value + } + if value, ok := cc.mutation.Status(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: category.FieldStatus, + }) + _node.Status = value + } + if value, ok := cc.mutation.Config(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeOther, + Value: value, + Column: category.FieldConfig, + }) + _node.Config = value + } + if value, ok := cc.mutation.Duration(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: value, + Column: category.FieldDuration, + }) + _node.Duration = value + } + if value, ok := cc.mutation.Count(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Value: value, + Column: category.FieldCount, + }) + _node.Count = value + } + if value, ok := cc.mutation.Strings(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: value, + Column: category.FieldStrings, + }) + _node.Strings = value + } + if nodes := cc.mutation.TodosIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// CategoryCreateBulk is the builder for creating many Category entities in bulk. +type CategoryCreateBulk struct { + config + builders []*CategoryCreate +} + +// Save creates the Category entities in the database. +func (ccb *CategoryCreateBulk) Save(ctx context.Context) ([]*Category, error) { + specs := make([]*sqlgraph.CreateSpec, len(ccb.builders)) + nodes := make([]*Category, len(ccb.builders)) + mutators := make([]Mutator, len(ccb.builders)) + for i := range ccb.builders { + func(i int, root context.Context) { + builder := ccb.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*CategoryMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, ccb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, ccb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, ccb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (ccb *CategoryCreateBulk) SaveX(ctx context.Context) []*Category { + v, err := ccb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ccb *CategoryCreateBulk) Exec(ctx context.Context) error { + _, err := ccb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ccb *CategoryCreateBulk) ExecX(ctx context.Context) { + if err := ccb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/entgql/internal/todoplugin/ent/category_delete.go b/entgql/internal/todoplugin/ent/category_delete.go new file mode 100644 index 000000000..68ec7693d --- /dev/null +++ b/entgql/internal/todoplugin/ent/category_delete.go @@ -0,0 +1,125 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// CategoryDelete is the builder for deleting a Category entity. +type CategoryDelete struct { + config + hooks []Hook + mutation *CategoryMutation +} + +// Where appends a list predicates to the CategoryDelete builder. +func (cd *CategoryDelete) Where(ps ...predicate.Category) *CategoryDelete { + cd.mutation.Where(ps...) + return cd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (cd *CategoryDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(cd.hooks) == 0 { + affected, err = cd.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*CategoryMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + cd.mutation = mutation + affected, err = cd.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(cd.hooks) - 1; i >= 0; i-- { + if cd.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = cd.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, cd.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cd *CategoryDelete) ExecX(ctx context.Context) int { + n, err := cd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (cd *CategoryDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: category.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: category.FieldID, + }, + }, + } + if ps := cd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, cd.driver, _spec) +} + +// CategoryDeleteOne is the builder for deleting a single Category entity. +type CategoryDeleteOne struct { + cd *CategoryDelete +} + +// Exec executes the deletion query. +func (cdo *CategoryDeleteOne) Exec(ctx context.Context) error { + n, err := cdo.cd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{category.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (cdo *CategoryDeleteOne) ExecX(ctx context.Context) { + cdo.cd.ExecX(ctx) +} diff --git a/entgql/internal/todoplugin/ent/category_query.go b/entgql/internal/todoplugin/ent/category_query.go new file mode 100644 index 000000000..588eaac0c --- /dev/null +++ b/entgql/internal/todoplugin/ent/category_query.go @@ -0,0 +1,1006 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "errors" + "fmt" + "math" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// CategoryQuery is the builder for querying Category entities. +type CategoryQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.Category + // eager-loading edges. + withTodos *TodoQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the CategoryQuery builder. +func (cq *CategoryQuery) Where(ps ...predicate.Category) *CategoryQuery { + cq.predicates = append(cq.predicates, ps...) + return cq +} + +// Limit adds a limit step to the query. +func (cq *CategoryQuery) Limit(limit int) *CategoryQuery { + cq.limit = &limit + return cq +} + +// Offset adds an offset step to the query. +func (cq *CategoryQuery) Offset(offset int) *CategoryQuery { + cq.offset = &offset + return cq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (cq *CategoryQuery) Unique(unique bool) *CategoryQuery { + cq.unique = &unique + return cq +} + +// Order adds an order step to the query. +func (cq *CategoryQuery) Order(o ...OrderFunc) *CategoryQuery { + cq.order = append(cq.order, o...) + return cq +} + +// QueryTodos chains the current query on the "todos" edge. +func (cq *CategoryQuery) QueryTodos() *TodoQuery { + query := &TodoQuery{config: cq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := cq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := cq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(category.Table, category.FieldID, selector), + sqlgraph.To(todo.Table, todo.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, category.TodosTable, category.TodosColumn), + ) + fromU = sqlgraph.SetNeighbors(cq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Category entity from the query. +// Returns a *NotFoundError when no Category was found. +func (cq *CategoryQuery) First(ctx context.Context) (*Category, error) { + nodes, err := cq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{category.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (cq *CategoryQuery) FirstX(ctx context.Context) *Category { + node, err := cq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Category ID from the query. +// Returns a *NotFoundError when no Category ID was found. +func (cq *CategoryQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = cq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{category.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (cq *CategoryQuery) FirstIDX(ctx context.Context) int { + id, err := cq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Category entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one Category entity is not found. +// Returns a *NotFoundError when no Category entities are found. +func (cq *CategoryQuery) Only(ctx context.Context) (*Category, error) { + nodes, err := cq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{category.Label} + default: + return nil, &NotSingularError{category.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (cq *CategoryQuery) OnlyX(ctx context.Context) *Category { + node, err := cq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Category ID in the query. +// Returns a *NotSingularError when exactly one Category ID is not found. +// Returns a *NotFoundError when no entities are found. +func (cq *CategoryQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = cq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{category.Label} + default: + err = &NotSingularError{category.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (cq *CategoryQuery) OnlyIDX(ctx context.Context) int { + id, err := cq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Categories. +func (cq *CategoryQuery) All(ctx context.Context) ([]*Category, error) { + if err := cq.prepareQuery(ctx); err != nil { + return nil, err + } + return cq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (cq *CategoryQuery) AllX(ctx context.Context) []*Category { + nodes, err := cq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Category IDs. +func (cq *CategoryQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := cq.Select(category.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (cq *CategoryQuery) IDsX(ctx context.Context) []int { + ids, err := cq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (cq *CategoryQuery) Count(ctx context.Context) (int, error) { + if err := cq.prepareQuery(ctx); err != nil { + return 0, err + } + return cq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (cq *CategoryQuery) CountX(ctx context.Context) int { + count, err := cq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (cq *CategoryQuery) Exist(ctx context.Context) (bool, error) { + if err := cq.prepareQuery(ctx); err != nil { + return false, err + } + return cq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (cq *CategoryQuery) ExistX(ctx context.Context) bool { + exist, err := cq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the CategoryQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (cq *CategoryQuery) Clone() *CategoryQuery { + if cq == nil { + return nil + } + return &CategoryQuery{ + config: cq.config, + limit: cq.limit, + offset: cq.offset, + order: append([]OrderFunc{}, cq.order...), + predicates: append([]predicate.Category{}, cq.predicates...), + withTodos: cq.withTodos.Clone(), + // clone intermediate query. + sql: cq.sql.Clone(), + path: cq.path, + } +} + +// WithTodos tells the query-builder to eager-load the nodes that are connected to +// the "todos" edge. The optional arguments are used to configure the query builder of the edge. +func (cq *CategoryQuery) WithTodos(opts ...func(*TodoQuery)) *CategoryQuery { + query := &TodoQuery{config: cq.config} + for _, opt := range opts { + opt(query) + } + cq.withTodos = query + return cq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Text string `json:"text,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Category.Query(). +// GroupBy(category.FieldText). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (cq *CategoryQuery) GroupBy(field string, fields ...string) *CategoryGroupBy { + group := &CategoryGroupBy{config: cq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := cq.prepareQuery(ctx); err != nil { + return nil, err + } + return cq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Text string `json:"text,omitempty"` +// } +// +// client.Category.Query(). +// Select(category.FieldText). +// Scan(ctx, &v) +// +func (cq *CategoryQuery) Select(fields ...string) *CategorySelect { + cq.fields = append(cq.fields, fields...) + return &CategorySelect{CategoryQuery: cq} +} + +func (cq *CategoryQuery) prepareQuery(ctx context.Context) error { + for _, f := range cq.fields { + if !category.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if cq.path != nil { + prev, err := cq.path(ctx) + if err != nil { + return err + } + cq.sql = prev + } + return nil +} + +func (cq *CategoryQuery) sqlAll(ctx context.Context) ([]*Category, error) { + var ( + nodes = []*Category{} + _spec = cq.querySpec() + loadedTypes = [1]bool{ + cq.withTodos != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &Category{config: cq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, cq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := cq.withTodos; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Category) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + nodes[i].Edges.Todos = []*Todo{} + } + query.withFKs = true + query.Where(predicate.Todo(func(s *sql.Selector) { + s.Where(sql.InValues(category.TodosColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + fk := n.category_todos + if fk == nil { + return nil, fmt.Errorf(`foreign-key "category_todos" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "category_todos" returned %v for node %v`, *fk, n.ID) + } + node.Edges.Todos = append(node.Edges.Todos, n) + } + } + + return nodes, nil +} + +func (cq *CategoryQuery) sqlCount(ctx context.Context) (int, error) { + _spec := cq.querySpec() + _spec.Node.Columns = cq.fields + if len(cq.fields) > 0 { + _spec.Unique = cq.unique != nil && *cq.unique + } + return sqlgraph.CountNodes(ctx, cq.driver, _spec) +} + +func (cq *CategoryQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := cq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (cq *CategoryQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: category.Table, + Columns: category.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: category.FieldID, + }, + }, + From: cq.sql, + Unique: true, + } + if unique := cq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := cq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, category.FieldID) + for i := range fields { + if fields[i] != category.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := cq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := cq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := cq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := cq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (cq *CategoryQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(cq.driver.Dialect()) + t1 := builder.Table(category.Table) + columns := cq.fields + if len(columns) == 0 { + columns = category.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if cq.sql != nil { + selector = cq.sql + selector.Select(selector.Columns(columns...)...) + } + if cq.unique != nil && *cq.unique { + selector.Distinct() + } + for _, p := range cq.predicates { + p(selector) + } + for _, p := range cq.order { + p(selector) + } + if offset := cq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := cq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// CategoryGroupBy is the group-by builder for Category entities. +type CategoryGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (cgb *CategoryGroupBy) Aggregate(fns ...AggregateFunc) *CategoryGroupBy { + cgb.fns = append(cgb.fns, fns...) + return cgb +} + +// Scan applies the group-by query and scans the result into the given value. +func (cgb *CategoryGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := cgb.path(ctx) + if err != nil { + return err + } + cgb.sql = query + return cgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (cgb *CategoryGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := cgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("ent: CategoryGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (cgb *CategoryGroupBy) StringsX(ctx context.Context) []string { + v, err := cgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = cgb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategoryGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (cgb *CategoryGroupBy) StringX(ctx context.Context) string { + v, err := cgb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("ent: CategoryGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (cgb *CategoryGroupBy) IntsX(ctx context.Context) []int { + v, err := cgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = cgb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategoryGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (cgb *CategoryGroupBy) IntX(ctx context.Context) int { + v, err := cgb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("ent: CategoryGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (cgb *CategoryGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := cgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = cgb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategoryGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (cgb *CategoryGroupBy) Float64X(ctx context.Context) float64 { + v, err := cgb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(cgb.fields) > 1 { + return nil, errors.New("ent: CategoryGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := cgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (cgb *CategoryGroupBy) BoolsX(ctx context.Context) []bool { + v, err := cgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (cgb *CategoryGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = cgb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategoryGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (cgb *CategoryGroupBy) BoolX(ctx context.Context) bool { + v, err := cgb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cgb *CategoryGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range cgb.fields { + if !category.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := cgb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := cgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (cgb *CategoryGroupBy) sqlQuery() *sql.Selector { + selector := cgb.sql.Select() + aggregation := make([]string, 0, len(cgb.fns)) + for _, fn := range cgb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(cgb.fields)+len(cgb.fns)) + for _, f := range cgb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(cgb.fields...)...) +} + +// CategorySelect is the builder for selecting fields of Category entities. +type CategorySelect struct { + *CategoryQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (cs *CategorySelect) Scan(ctx context.Context, v interface{}) error { + if err := cs.prepareQuery(ctx); err != nil { + return err + } + cs.sql = cs.CategoryQuery.sqlQuery(ctx) + return cs.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (cs *CategorySelect) ScanX(ctx context.Context, v interface{}) { + if err := cs.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Strings(ctx context.Context) ([]string, error) { + if len(cs.fields) > 1 { + return nil, errors.New("ent: CategorySelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (cs *CategorySelect) StringsX(ctx context.Context) []string { + v, err := cs.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = cs.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategorySelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (cs *CategorySelect) StringX(ctx context.Context) string { + v, err := cs.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Ints(ctx context.Context) ([]int, error) { + if len(cs.fields) > 1 { + return nil, errors.New("ent: CategorySelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (cs *CategorySelect) IntsX(ctx context.Context) []int { + v, err := cs.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = cs.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategorySelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (cs *CategorySelect) IntX(ctx context.Context) int { + v, err := cs.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Float64s(ctx context.Context) ([]float64, error) { + if len(cs.fields) > 1 { + return nil, errors.New("ent: CategorySelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (cs *CategorySelect) Float64sX(ctx context.Context) []float64 { + v, err := cs.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = cs.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategorySelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (cs *CategorySelect) Float64X(ctx context.Context) float64 { + v, err := cs.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Bools(ctx context.Context) ([]bool, error) { + if len(cs.fields) > 1 { + return nil, errors.New("ent: CategorySelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := cs.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (cs *CategorySelect) BoolsX(ctx context.Context) []bool { + v, err := cs.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (cs *CategorySelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = cs.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{category.Label} + default: + err = fmt.Errorf("ent: CategorySelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (cs *CategorySelect) BoolX(ctx context.Context) bool { + v, err := cs.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (cs *CategorySelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := cs.sql.Query() + if err := cs.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/entgql/internal/todoplugin/ent/category_update.go b/entgql/internal/todoplugin/ent/category_update.go new file mode 100644 index 000000000..02ae0700e --- /dev/null +++ b/entgql/internal/todoplugin/ent/category_update.go @@ -0,0 +1,818 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// CategoryUpdate is the builder for updating Category entities. +type CategoryUpdate struct { + config + hooks []Hook + mutation *CategoryMutation +} + +// Where appends a list predicates to the CategoryUpdate builder. +func (cu *CategoryUpdate) Where(ps ...predicate.Category) *CategoryUpdate { + cu.mutation.Where(ps...) + return cu +} + +// SetText sets the "text" field. +func (cu *CategoryUpdate) SetText(s string) *CategoryUpdate { + cu.mutation.SetText(s) + return cu +} + +// SetStatus sets the "status" field. +func (cu *CategoryUpdate) SetStatus(c category.Status) *CategoryUpdate { + cu.mutation.SetStatus(c) + return cu +} + +// SetConfig sets the "config" field. +func (cu *CategoryUpdate) SetConfig(sc *schematype.CategoryConfig) *CategoryUpdate { + cu.mutation.SetConfig(sc) + return cu +} + +// ClearConfig clears the value of the "config" field. +func (cu *CategoryUpdate) ClearConfig() *CategoryUpdate { + cu.mutation.ClearConfig() + return cu +} + +// SetDuration sets the "duration" field. +func (cu *CategoryUpdate) SetDuration(t time.Duration) *CategoryUpdate { + cu.mutation.ResetDuration() + cu.mutation.SetDuration(t) + return cu +} + +// SetNillableDuration sets the "duration" field if the given value is not nil. +func (cu *CategoryUpdate) SetNillableDuration(t *time.Duration) *CategoryUpdate { + if t != nil { + cu.SetDuration(*t) + } + return cu +} + +// AddDuration adds t to the "duration" field. +func (cu *CategoryUpdate) AddDuration(t time.Duration) *CategoryUpdate { + cu.mutation.AddDuration(t) + return cu +} + +// ClearDuration clears the value of the "duration" field. +func (cu *CategoryUpdate) ClearDuration() *CategoryUpdate { + cu.mutation.ClearDuration() + return cu +} + +// SetCount sets the "count" field. +func (cu *CategoryUpdate) SetCount(u uint64) *CategoryUpdate { + cu.mutation.ResetCount() + cu.mutation.SetCount(u) + return cu +} + +// SetNillableCount sets the "count" field if the given value is not nil. +func (cu *CategoryUpdate) SetNillableCount(u *uint64) *CategoryUpdate { + if u != nil { + cu.SetCount(*u) + } + return cu +} + +// AddCount adds u to the "count" field. +func (cu *CategoryUpdate) AddCount(u int64) *CategoryUpdate { + cu.mutation.AddCount(u) + return cu +} + +// ClearCount clears the value of the "count" field. +func (cu *CategoryUpdate) ClearCount() *CategoryUpdate { + cu.mutation.ClearCount() + return cu +} + +// SetStrings sets the "strings" field. +func (cu *CategoryUpdate) SetStrings(s []string) *CategoryUpdate { + cu.mutation.SetStrings(s) + return cu +} + +// ClearStrings clears the value of the "strings" field. +func (cu *CategoryUpdate) ClearStrings() *CategoryUpdate { + cu.mutation.ClearStrings() + return cu +} + +// AddTodoIDs adds the "todos" edge to the Todo entity by IDs. +func (cu *CategoryUpdate) AddTodoIDs(ids ...int) *CategoryUpdate { + cu.mutation.AddTodoIDs(ids...) + return cu +} + +// AddTodos adds the "todos" edges to the Todo entity. +func (cu *CategoryUpdate) AddTodos(t ...*Todo) *CategoryUpdate { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return cu.AddTodoIDs(ids...) +} + +// Mutation returns the CategoryMutation object of the builder. +func (cu *CategoryUpdate) Mutation() *CategoryMutation { + return cu.mutation +} + +// ClearTodos clears all "todos" edges to the Todo entity. +func (cu *CategoryUpdate) ClearTodos() *CategoryUpdate { + cu.mutation.ClearTodos() + return cu +} + +// RemoveTodoIDs removes the "todos" edge to Todo entities by IDs. +func (cu *CategoryUpdate) RemoveTodoIDs(ids ...int) *CategoryUpdate { + cu.mutation.RemoveTodoIDs(ids...) + return cu +} + +// RemoveTodos removes "todos" edges to Todo entities. +func (cu *CategoryUpdate) RemoveTodos(t ...*Todo) *CategoryUpdate { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return cu.RemoveTodoIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (cu *CategoryUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(cu.hooks) == 0 { + if err = cu.check(); err != nil { + return 0, err + } + affected, err = cu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*CategoryMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = cu.check(); err != nil { + return 0, err + } + cu.mutation = mutation + affected, err = cu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(cu.hooks) - 1; i >= 0; i-- { + if cu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = cu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, cu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (cu *CategoryUpdate) SaveX(ctx context.Context) int { + affected, err := cu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (cu *CategoryUpdate) Exec(ctx context.Context) error { + _, err := cu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cu *CategoryUpdate) ExecX(ctx context.Context) { + if err := cu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (cu *CategoryUpdate) check() error { + if v, ok := cu.mutation.Text(); ok { + if err := category.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Category.text": %w`, err)} + } + } + if v, ok := cu.mutation.Status(); ok { + if err := category.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Category.status": %w`, err)} + } + } + return nil +} + +func (cu *CategoryUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: category.Table, + Columns: category.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: category.FieldID, + }, + }, + } + if ps := cu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := cu.mutation.Text(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: category.FieldText, + }) + } + if value, ok := cu.mutation.Status(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: category.FieldStatus, + }) + } + if value, ok := cu.mutation.Config(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeOther, + Value: value, + Column: category.FieldConfig, + }) + } + if cu.mutation.ConfigCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeOther, + Column: category.FieldConfig, + }) + } + if value, ok := cu.mutation.Duration(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: value, + Column: category.FieldDuration, + }) + } + if value, ok := cu.mutation.AddedDuration(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: value, + Column: category.FieldDuration, + }) + } + if cu.mutation.DurationCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: category.FieldDuration, + }) + } + if value, ok := cu.mutation.Count(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Value: value, + Column: category.FieldCount, + }) + } + if value, ok := cu.mutation.AddedCount(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Value: value, + Column: category.FieldCount, + }) + } + if cu.mutation.CountCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: category.FieldCount, + }) + } + if value, ok := cu.mutation.Strings(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: value, + Column: category.FieldStrings, + }) + } + if cu.mutation.StringsCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: category.FieldStrings, + }) + } + if cu.mutation.TodosCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := cu.mutation.RemovedTodosIDs(); len(nodes) > 0 && !cu.mutation.TodosCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := cu.mutation.TodosIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, cu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{category.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// CategoryUpdateOne is the builder for updating a single Category entity. +type CategoryUpdateOne struct { + config + fields []string + hooks []Hook + mutation *CategoryMutation +} + +// SetText sets the "text" field. +func (cuo *CategoryUpdateOne) SetText(s string) *CategoryUpdateOne { + cuo.mutation.SetText(s) + return cuo +} + +// SetStatus sets the "status" field. +func (cuo *CategoryUpdateOne) SetStatus(c category.Status) *CategoryUpdateOne { + cuo.mutation.SetStatus(c) + return cuo +} + +// SetConfig sets the "config" field. +func (cuo *CategoryUpdateOne) SetConfig(sc *schematype.CategoryConfig) *CategoryUpdateOne { + cuo.mutation.SetConfig(sc) + return cuo +} + +// ClearConfig clears the value of the "config" field. +func (cuo *CategoryUpdateOne) ClearConfig() *CategoryUpdateOne { + cuo.mutation.ClearConfig() + return cuo +} + +// SetDuration sets the "duration" field. +func (cuo *CategoryUpdateOne) SetDuration(t time.Duration) *CategoryUpdateOne { + cuo.mutation.ResetDuration() + cuo.mutation.SetDuration(t) + return cuo +} + +// SetNillableDuration sets the "duration" field if the given value is not nil. +func (cuo *CategoryUpdateOne) SetNillableDuration(t *time.Duration) *CategoryUpdateOne { + if t != nil { + cuo.SetDuration(*t) + } + return cuo +} + +// AddDuration adds t to the "duration" field. +func (cuo *CategoryUpdateOne) AddDuration(t time.Duration) *CategoryUpdateOne { + cuo.mutation.AddDuration(t) + return cuo +} + +// ClearDuration clears the value of the "duration" field. +func (cuo *CategoryUpdateOne) ClearDuration() *CategoryUpdateOne { + cuo.mutation.ClearDuration() + return cuo +} + +// SetCount sets the "count" field. +func (cuo *CategoryUpdateOne) SetCount(u uint64) *CategoryUpdateOne { + cuo.mutation.ResetCount() + cuo.mutation.SetCount(u) + return cuo +} + +// SetNillableCount sets the "count" field if the given value is not nil. +func (cuo *CategoryUpdateOne) SetNillableCount(u *uint64) *CategoryUpdateOne { + if u != nil { + cuo.SetCount(*u) + } + return cuo +} + +// AddCount adds u to the "count" field. +func (cuo *CategoryUpdateOne) AddCount(u int64) *CategoryUpdateOne { + cuo.mutation.AddCount(u) + return cuo +} + +// ClearCount clears the value of the "count" field. +func (cuo *CategoryUpdateOne) ClearCount() *CategoryUpdateOne { + cuo.mutation.ClearCount() + return cuo +} + +// SetStrings sets the "strings" field. +func (cuo *CategoryUpdateOne) SetStrings(s []string) *CategoryUpdateOne { + cuo.mutation.SetStrings(s) + return cuo +} + +// ClearStrings clears the value of the "strings" field. +func (cuo *CategoryUpdateOne) ClearStrings() *CategoryUpdateOne { + cuo.mutation.ClearStrings() + return cuo +} + +// AddTodoIDs adds the "todos" edge to the Todo entity by IDs. +func (cuo *CategoryUpdateOne) AddTodoIDs(ids ...int) *CategoryUpdateOne { + cuo.mutation.AddTodoIDs(ids...) + return cuo +} + +// AddTodos adds the "todos" edges to the Todo entity. +func (cuo *CategoryUpdateOne) AddTodos(t ...*Todo) *CategoryUpdateOne { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return cuo.AddTodoIDs(ids...) +} + +// Mutation returns the CategoryMutation object of the builder. +func (cuo *CategoryUpdateOne) Mutation() *CategoryMutation { + return cuo.mutation +} + +// ClearTodos clears all "todos" edges to the Todo entity. +func (cuo *CategoryUpdateOne) ClearTodos() *CategoryUpdateOne { + cuo.mutation.ClearTodos() + return cuo +} + +// RemoveTodoIDs removes the "todos" edge to Todo entities by IDs. +func (cuo *CategoryUpdateOne) RemoveTodoIDs(ids ...int) *CategoryUpdateOne { + cuo.mutation.RemoveTodoIDs(ids...) + return cuo +} + +// RemoveTodos removes "todos" edges to Todo entities. +func (cuo *CategoryUpdateOne) RemoveTodos(t ...*Todo) *CategoryUpdateOne { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return cuo.RemoveTodoIDs(ids...) +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (cuo *CategoryUpdateOne) Select(field string, fields ...string) *CategoryUpdateOne { + cuo.fields = append([]string{field}, fields...) + return cuo +} + +// Save executes the query and returns the updated Category entity. +func (cuo *CategoryUpdateOne) Save(ctx context.Context) (*Category, error) { + var ( + err error + node *Category + ) + if len(cuo.hooks) == 0 { + if err = cuo.check(); err != nil { + return nil, err + } + node, err = cuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*CategoryMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = cuo.check(); err != nil { + return nil, err + } + cuo.mutation = mutation + node, err = cuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(cuo.hooks) - 1; i >= 0; i-- { + if cuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = cuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, cuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (cuo *CategoryUpdateOne) SaveX(ctx context.Context) *Category { + node, err := cuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (cuo *CategoryUpdateOne) Exec(ctx context.Context) error { + _, err := cuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (cuo *CategoryUpdateOne) ExecX(ctx context.Context) { + if err := cuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (cuo *CategoryUpdateOne) check() error { + if v, ok := cuo.mutation.Text(); ok { + if err := category.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Category.text": %w`, err)} + } + } + if v, ok := cuo.mutation.Status(); ok { + if err := category.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Category.status": %w`, err)} + } + } + return nil +} + +func (cuo *CategoryUpdateOne) sqlSave(ctx context.Context) (_node *Category, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: category.Table, + Columns: category.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: category.FieldID, + }, + }, + } + id, ok := cuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Category.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := cuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, category.FieldID) + for _, f := range fields { + if !category.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != category.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := cuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := cuo.mutation.Text(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: category.FieldText, + }) + } + if value, ok := cuo.mutation.Status(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: category.FieldStatus, + }) + } + if value, ok := cuo.mutation.Config(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeOther, + Value: value, + Column: category.FieldConfig, + }) + } + if cuo.mutation.ConfigCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeOther, + Column: category.FieldConfig, + }) + } + if value, ok := cuo.mutation.Duration(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: value, + Column: category.FieldDuration, + }) + } + if value, ok := cuo.mutation.AddedDuration(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Value: value, + Column: category.FieldDuration, + }) + } + if cuo.mutation.DurationCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: category.FieldDuration, + }) + } + if value, ok := cuo.mutation.Count(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Value: value, + Column: category.FieldCount, + }) + } + if value, ok := cuo.mutation.AddedCount(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Value: value, + Column: category.FieldCount, + }) + } + if cuo.mutation.CountCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeUint64, + Column: category.FieldCount, + }) + } + if value, ok := cuo.mutation.Strings(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Value: value, + Column: category.FieldStrings, + }) + } + if cuo.mutation.StringsCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeJSON, + Column: category.FieldStrings, + }) + } + if cuo.mutation.TodosCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := cuo.mutation.RemovedTodosIDs(); len(nodes) > 0 && !cuo.mutation.TodosCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := cuo.mutation.TodosIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: category.TodosTable, + Columns: []string{category.TodosColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Category{config: cuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, cuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{category.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/entgql/internal/todoplugin/ent/client.go b/entgql/internal/todoplugin/ent/client.go new file mode 100644 index 000000000..613fb120b --- /dev/null +++ b/entgql/internal/todoplugin/ent/client.go @@ -0,0 +1,471 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + "log" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/migrate" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +// Client is the client that holds all ent builders. +type Client struct { + config + // Schema is the client for creating, migrating and dropping schema. + Schema *migrate.Schema + // Category is the client for interacting with the Category builders. + Category *CategoryClient + // Todo is the client for interacting with the Todo builders. + Todo *TodoClient + // User is the client for interacting with the User builders. + User *UserClient + // additional fields for node api + tables tables +} + +// NewClient creates a new client configured with the given options. +func NewClient(opts ...Option) *Client { + cfg := config{log: log.Println, hooks: &hooks{}} + cfg.options(opts...) + client := &Client{config: cfg} + client.init() + return client +} + +func (c *Client) init() { + c.Schema = migrate.NewSchema(c.driver) + c.Category = NewCategoryClient(c.config) + c.Todo = NewTodoClient(c.config) + c.User = NewUserClient(c.config) +} + +// Open opens a database/sql.DB specified by the driver name and +// the data source name, and returns a new client attached to it. +// Optional parameters can be added for configuring the client. +func Open(driverName, dataSourceName string, options ...Option) (*Client, error) { + switch driverName { + case dialect.MySQL, dialect.Postgres, dialect.SQLite: + drv, err := sql.Open(driverName, dataSourceName) + if err != nil { + return nil, err + } + return NewClient(append(options, Driver(drv))...), nil + default: + return nil, fmt.Errorf("unsupported driver: %q", driverName) + } +} + +// Tx returns a new transactional client. The provided context +// is used until the transaction is committed or rolled back. +func (c *Client) Tx(ctx context.Context) (*Tx, error) { + if _, ok := c.driver.(*txDriver); ok { + return nil, fmt.Errorf("ent: cannot start a transaction within a transaction") + } + tx, err := newTx(ctx, c.driver) + if err != nil { + return nil, fmt.Errorf("ent: starting a transaction: %w", err) + } + cfg := c.config + cfg.driver = tx + return &Tx{ + ctx: ctx, + config: cfg, + Category: NewCategoryClient(cfg), + Todo: NewTodoClient(cfg), + User: NewUserClient(cfg), + }, nil +} + +// BeginTx returns a transactional client with specified options. +func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { + if _, ok := c.driver.(*txDriver); ok { + return nil, fmt.Errorf("ent: cannot start a transaction within a transaction") + } + tx, err := c.driver.(interface { + BeginTx(context.Context, *sql.TxOptions) (dialect.Tx, error) + }).BeginTx(ctx, opts) + if err != nil { + return nil, fmt.Errorf("ent: starting a transaction: %w", err) + } + cfg := c.config + cfg.driver = &txDriver{tx: tx, drv: c.driver} + return &Tx{ + config: cfg, + Category: NewCategoryClient(cfg), + Todo: NewTodoClient(cfg), + User: NewUserClient(cfg), + }, nil +} + +// Debug returns a new debug-client. It's used to get verbose logging on specific operations. +// +// client.Debug(). +// Category. +// Query(). +// Count(ctx) +// +func (c *Client) Debug() *Client { + if c.debug { + return c + } + cfg := c.config + cfg.driver = dialect.Debug(c.driver, c.log) + client := &Client{config: cfg} + client.init() + return client +} + +// Close closes the database connection and prevents new queries from starting. +func (c *Client) Close() error { + return c.driver.Close() +} + +// Use adds the mutation hooks to all the entity clients. +// In order to add hooks to a specific client, call: `client.Node.Use(...)`. +func (c *Client) Use(hooks ...Hook) { + c.Category.Use(hooks...) + c.Todo.Use(hooks...) + c.User.Use(hooks...) +} + +// CategoryClient is a client for the Category schema. +type CategoryClient struct { + config +} + +// NewCategoryClient returns a client for the Category from the given config. +func NewCategoryClient(c config) *CategoryClient { + return &CategoryClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `category.Hooks(f(g(h())))`. +func (c *CategoryClient) Use(hooks ...Hook) { + c.hooks.Category = append(c.hooks.Category, hooks...) +} + +// Create returns a create builder for Category. +func (c *CategoryClient) Create() *CategoryCreate { + mutation := newCategoryMutation(c.config, OpCreate) + return &CategoryCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Category entities. +func (c *CategoryClient) CreateBulk(builders ...*CategoryCreate) *CategoryCreateBulk { + return &CategoryCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Category. +func (c *CategoryClient) Update() *CategoryUpdate { + mutation := newCategoryMutation(c.config, OpUpdate) + return &CategoryUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *CategoryClient) UpdateOne(ca *Category) *CategoryUpdateOne { + mutation := newCategoryMutation(c.config, OpUpdateOne, withCategory(ca)) + return &CategoryUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *CategoryClient) UpdateOneID(id int) *CategoryUpdateOne { + mutation := newCategoryMutation(c.config, OpUpdateOne, withCategoryID(id)) + return &CategoryUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Category. +func (c *CategoryClient) Delete() *CategoryDelete { + mutation := newCategoryMutation(c.config, OpDelete) + return &CategoryDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *CategoryClient) DeleteOne(ca *Category) *CategoryDeleteOne { + return c.DeleteOneID(ca.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *CategoryClient) DeleteOneID(id int) *CategoryDeleteOne { + builder := c.Delete().Where(category.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &CategoryDeleteOne{builder} +} + +// Query returns a query builder for Category. +func (c *CategoryClient) Query() *CategoryQuery { + return &CategoryQuery{ + config: c.config, + } +} + +// Get returns a Category entity by its id. +func (c *CategoryClient) Get(ctx context.Context, id int) (*Category, error) { + return c.Query().Where(category.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *CategoryClient) GetX(ctx context.Context, id int) *Category { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryTodos queries the todos edge of a Category. +func (c *CategoryClient) QueryTodos(ca *Category) *TodoQuery { + query := &TodoQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := ca.ID + step := sqlgraph.NewStep( + sqlgraph.From(category.Table, category.FieldID, id), + sqlgraph.To(todo.Table, todo.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, category.TodosTable, category.TodosColumn), + ) + fromV = sqlgraph.Neighbors(ca.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *CategoryClient) Hooks() []Hook { + return c.hooks.Category +} + +// TodoClient is a client for the Todo schema. +type TodoClient struct { + config +} + +// NewTodoClient returns a client for the Todo from the given config. +func NewTodoClient(c config) *TodoClient { + return &TodoClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `todo.Hooks(f(g(h())))`. +func (c *TodoClient) Use(hooks ...Hook) { + c.hooks.Todo = append(c.hooks.Todo, hooks...) +} + +// Create returns a create builder for Todo. +func (c *TodoClient) Create() *TodoCreate { + mutation := newTodoMutation(c.config, OpCreate) + return &TodoCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of Todo entities. +func (c *TodoClient) CreateBulk(builders ...*TodoCreate) *TodoCreateBulk { + return &TodoCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for Todo. +func (c *TodoClient) Update() *TodoUpdate { + mutation := newTodoMutation(c.config, OpUpdate) + return &TodoUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *TodoClient) UpdateOne(t *Todo) *TodoUpdateOne { + mutation := newTodoMutation(c.config, OpUpdateOne, withTodo(t)) + return &TodoUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *TodoClient) UpdateOneID(id int) *TodoUpdateOne { + mutation := newTodoMutation(c.config, OpUpdateOne, withTodoID(id)) + return &TodoUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for Todo. +func (c *TodoClient) Delete() *TodoDelete { + mutation := newTodoMutation(c.config, OpDelete) + return &TodoDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *TodoClient) DeleteOne(t *Todo) *TodoDeleteOne { + return c.DeleteOneID(t.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *TodoClient) DeleteOneID(id int) *TodoDeleteOne { + builder := c.Delete().Where(todo.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &TodoDeleteOne{builder} +} + +// Query returns a query builder for Todo. +func (c *TodoClient) Query() *TodoQuery { + return &TodoQuery{ + config: c.config, + } +} + +// Get returns a Todo entity by its id. +func (c *TodoClient) Get(ctx context.Context, id int) (*Todo, error) { + return c.Query().Where(todo.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *TodoClient) GetX(ctx context.Context, id int) *Todo { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryParent queries the parent edge of a Todo. +func (c *TodoClient) QueryParent(t *Todo) *TodoQuery { + query := &TodoQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := t.ID + step := sqlgraph.NewStep( + sqlgraph.From(todo.Table, todo.FieldID, id), + sqlgraph.To(todo.Table, todo.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, todo.ParentTable, todo.ParentColumn), + ) + fromV = sqlgraph.Neighbors(t.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryChildren queries the children edge of a Todo. +func (c *TodoClient) QueryChildren(t *Todo) *TodoQuery { + query := &TodoQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := t.ID + step := sqlgraph.NewStep( + sqlgraph.From(todo.Table, todo.FieldID, id), + sqlgraph.To(todo.Table, todo.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, todo.ChildrenTable, todo.ChildrenColumn), + ) + fromV = sqlgraph.Neighbors(t.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *TodoClient) Hooks() []Hook { + return c.hooks.Todo +} + +// UserClient is a client for the User schema. +type UserClient struct { + config +} + +// NewUserClient returns a client for the User from the given config. +func NewUserClient(c config) *UserClient { + return &UserClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `user.Hooks(f(g(h())))`. +func (c *UserClient) Use(hooks ...Hook) { + c.hooks.User = append(c.hooks.User, hooks...) +} + +// Create returns a create builder for User. +func (c *UserClient) Create() *UserCreate { + mutation := newUserMutation(c.config, OpCreate) + return &UserCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of User entities. +func (c *UserClient) CreateBulk(builders ...*UserCreate) *UserCreateBulk { + return &UserCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for User. +func (c *UserClient) Update() *UserUpdate { + mutation := newUserMutation(c.config, OpUpdate) + return &UserUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *UserClient) UpdateOne(u *User) *UserUpdateOne { + mutation := newUserMutation(c.config, OpUpdateOne, withUser(u)) + return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *UserClient) UpdateOneID(id int) *UserUpdateOne { + mutation := newUserMutation(c.config, OpUpdateOne, withUserID(id)) + return &UserUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for User. +func (c *UserClient) Delete() *UserDelete { + mutation := newUserMutation(c.config, OpDelete) + return &UserDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a delete builder for the given entity. +func (c *UserClient) DeleteOne(u *User) *UserDeleteOne { + return c.DeleteOneID(u.ID) +} + +// DeleteOneID returns a delete builder for the given id. +func (c *UserClient) DeleteOneID(id int) *UserDeleteOne { + builder := c.Delete().Where(user.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &UserDeleteOne{builder} +} + +// Query returns a query builder for User. +func (c *UserClient) Query() *UserQuery { + return &UserQuery{ + config: c.config, + } +} + +// Get returns a User entity by its id. +func (c *UserClient) Get(ctx context.Context, id int) (*User, error) { + return c.Query().Where(user.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *UserClient) GetX(ctx context.Context, id int) *User { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// Hooks returns the client hooks. +func (c *UserClient) Hooks() []Hook { + return c.hooks.User +} diff --git a/entgql/internal/todoplugin/ent/config.go b/entgql/internal/todoplugin/ent/config.go new file mode 100644 index 000000000..050a626ea --- /dev/null +++ b/entgql/internal/todoplugin/ent/config.go @@ -0,0 +1,75 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect" +) + +// Option function to configure the client. +type Option func(*config) + +// Config is the configuration for the client and its builder. +type config struct { + // driver used for executing database requests. + driver dialect.Driver + // debug enable a debug logging. + debug bool + // log used for logging on debug mode. + log func(...interface{}) + // hooks to execute on mutations. + hooks *hooks +} + +// hooks per client, for fast access. +type hooks struct { + Category []ent.Hook + Todo []ent.Hook + User []ent.Hook +} + +// Options applies the options on the config object. +func (c *config) options(opts ...Option) { + for _, opt := range opts { + opt(c) + } + if c.debug { + c.driver = dialect.Debug(c.driver, c.log) + } +} + +// Debug enables debug logging on the ent.Driver. +func Debug() Option { + return func(c *config) { + c.debug = true + } +} + +// Log sets the logging function for debug mode. +func Log(fn func(...interface{})) Option { + return func(c *config) { + c.log = fn + } +} + +// Driver configures the client driver. +func Driver(driver dialect.Driver) Option { + return func(c *config) { + c.driver = driver + } +} diff --git a/entgql/internal/todoplugin/ent/context.go b/entgql/internal/todoplugin/ent/context.go new file mode 100644 index 000000000..94581ab0d --- /dev/null +++ b/entgql/internal/todoplugin/ent/context.go @@ -0,0 +1,47 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" +) + +type clientCtxKey struct{} + +// FromContext returns a Client stored inside a context, or nil if there isn't one. +func FromContext(ctx context.Context) *Client { + c, _ := ctx.Value(clientCtxKey{}).(*Client) + return c +} + +// NewContext returns a new context with the given Client attached. +func NewContext(parent context.Context, c *Client) context.Context { + return context.WithValue(parent, clientCtxKey{}, c) +} + +type txCtxKey struct{} + +// TxFromContext returns a Tx stored inside a context, or nil if there isn't one. +func TxFromContext(ctx context.Context) *Tx { + tx, _ := ctx.Value(txCtxKey{}).(*Tx) + return tx +} + +// NewTxContext returns a new context with the given Tx attached. +func NewTxContext(parent context.Context, tx *Tx) context.Context { + return context.WithValue(parent, txCtxKey{}, tx) +} diff --git a/entgql/internal/todoplugin/ent/ent.go b/entgql/internal/todoplugin/ent/ent.go new file mode 100644 index 000000000..c0b210a29 --- /dev/null +++ b/entgql/internal/todoplugin/ent/ent.go @@ -0,0 +1,277 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "errors" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent" + "entgo.io/ent/dialect/sql" +) + +// ent aliases to avoid import conflicts in user's code. +type ( + Op = ent.Op + Hook = ent.Hook + Value = ent.Value + Query = ent.Query + Policy = ent.Policy + Mutator = ent.Mutator + Mutation = ent.Mutation + MutateFunc = ent.MutateFunc +) + +// OrderFunc applies an ordering on the sql selector. +type OrderFunc func(*sql.Selector) + +// columnChecker returns a function indicates if the column exists in the given column. +func columnChecker(table string) func(string) error { + checks := map[string]func(string) bool{ + category.Table: category.ValidColumn, + todo.Table: todo.ValidColumn, + user.Table: user.ValidColumn, + } + check, ok := checks[table] + if !ok { + return func(string) error { + return fmt.Errorf("unknown table %q", table) + } + } + return func(column string) error { + if !check(column) { + return fmt.Errorf("unknown column %q for table %q", column, table) + } + return nil + } +} + +// Asc applies the given fields in ASC order. +func Asc(fields ...string) OrderFunc { + return func(s *sql.Selector) { + check := columnChecker(s.TableName()) + for _, f := range fields { + if err := check(f); err != nil { + s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)}) + } + s.OrderBy(sql.Asc(s.C(f))) + } + } +} + +// Desc applies the given fields in DESC order. +func Desc(fields ...string) OrderFunc { + return func(s *sql.Selector) { + check := columnChecker(s.TableName()) + for _, f := range fields { + if err := check(f); err != nil { + s.AddError(&ValidationError{Name: f, err: fmt.Errorf("ent: %w", err)}) + } + s.OrderBy(sql.Desc(s.C(f))) + } + } +} + +// AggregateFunc applies an aggregation step on the group-by traversal/selector. +type AggregateFunc func(*sql.Selector) string + +// As is a pseudo aggregation function for renaming another other functions with custom names. For example: +// +// GroupBy(field1, field2). +// Aggregate(ent.As(ent.Sum(field1), "sum_field1"), (ent.As(ent.Sum(field2), "sum_field2")). +// Scan(ctx, &v) +// +func As(fn AggregateFunc, end string) AggregateFunc { + return func(s *sql.Selector) string { + return sql.As(fn(s), end) + } +} + +// Count applies the "count" aggregation function on each group. +func Count() AggregateFunc { + return func(s *sql.Selector) string { + return sql.Count("*") + } +} + +// Max applies the "max" aggregation function on the given field of each group. +func Max(field string) AggregateFunc { + return func(s *sql.Selector) string { + check := columnChecker(s.TableName()) + if err := check(field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Max(s.C(field)) + } +} + +// Mean applies the "mean" aggregation function on the given field of each group. +func Mean(field string) AggregateFunc { + return func(s *sql.Selector) string { + check := columnChecker(s.TableName()) + if err := check(field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Avg(s.C(field)) + } +} + +// Min applies the "min" aggregation function on the given field of each group. +func Min(field string) AggregateFunc { + return func(s *sql.Selector) string { + check := columnChecker(s.TableName()) + if err := check(field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Min(s.C(field)) + } +} + +// Sum applies the "sum" aggregation function on the given field of each group. +func Sum(field string) AggregateFunc { + return func(s *sql.Selector) string { + check := columnChecker(s.TableName()) + if err := check(field); err != nil { + s.AddError(&ValidationError{Name: field, err: fmt.Errorf("ent: %w", err)}) + return "" + } + return sql.Sum(s.C(field)) + } +} + +// ValidationError returns when validating a field or edge fails. +type ValidationError struct { + Name string // Field or edge name. + err error +} + +// Error implements the error interface. +func (e *ValidationError) Error() string { + return e.err.Error() +} + +// Unwrap implements the errors.Wrapper interface. +func (e *ValidationError) Unwrap() error { + return e.err +} + +// IsValidationError returns a boolean indicating whether the error is a validation error. +func IsValidationError(err error) bool { + if err == nil { + return false + } + var e *ValidationError + return errors.As(err, &e) +} + +// NotFoundError returns when trying to fetch a specific entity and it was not found in the database. +type NotFoundError struct { + label string +} + +// Error implements the error interface. +func (e *NotFoundError) Error() string { + return "ent: " + e.label + " not found" +} + +// IsNotFound returns a boolean indicating whether the error is a not found error. +func IsNotFound(err error) bool { + if err == nil { + return false + } + var e *NotFoundError + return errors.As(err, &e) +} + +// MaskNotFound masks not found error. +func MaskNotFound(err error) error { + if IsNotFound(err) { + return nil + } + return err +} + +// NotSingularError returns when trying to fetch a singular entity and more then one was found in the database. +type NotSingularError struct { + label string +} + +// Error implements the error interface. +func (e *NotSingularError) Error() string { + return "ent: " + e.label + " not singular" +} + +// IsNotSingular returns a boolean indicating whether the error is a not singular error. +func IsNotSingular(err error) bool { + if err == nil { + return false + } + var e *NotSingularError + return errors.As(err, &e) +} + +// NotLoadedError returns when trying to get a node that was not loaded by the query. +type NotLoadedError struct { + edge string +} + +// Error implements the error interface. +func (e *NotLoadedError) Error() string { + return "ent: " + e.edge + " edge was not loaded" +} + +// IsNotLoaded returns a boolean indicating whether the error is a not loaded error. +func IsNotLoaded(err error) bool { + if err == nil { + return false + } + var e *NotLoadedError + return errors.As(err, &e) +} + +// ConstraintError returns when trying to create/update one or more entities and +// one or more of their constraints failed. For example, violation of edge or +// field uniqueness. +type ConstraintError struct { + msg string + wrap error +} + +// Error implements the error interface. +func (e ConstraintError) Error() string { + return "ent: constraint failed: " + e.msg +} + +// Unwrap implements the errors.Wrapper interface. +func (e *ConstraintError) Unwrap() error { + return e.wrap +} + +// IsConstraintError returns a boolean indicating whether the error is a constraint failure. +func IsConstraintError(err error) bool { + if err == nil { + return false + } + var e *ConstraintError + return errors.As(err, &e) +} diff --git a/entgql/internal/todoplugin/ent/entc.go b/entgql/internal/todoplugin/ent/entc.go new file mode 100644 index 000000000..6c5e4a1d7 --- /dev/null +++ b/entgql/internal/todoplugin/ent/entc.go @@ -0,0 +1,12 @@ +// Copyright 2019-present Facebook Inc. All rights reserved. +// This source code is licensed under the Apache 2.0 license found +// in the LICENSE file in the root directory of this source tree. + +//go:build ignore +// +build ignore + +package main + +func main() { + +} diff --git a/entgql/internal/todoplugin/ent/enttest/enttest.go b/entgql/internal/todoplugin/ent/enttest/enttest.go new file mode 100644 index 000000000..cc4e5eab6 --- /dev/null +++ b/entgql/internal/todoplugin/ent/enttest/enttest.go @@ -0,0 +1,92 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package enttest + +import ( + "context" + + "entgo.io/contrib/entgql/internal/todoplugin/ent" + // required by schema hooks. + _ "entgo.io/contrib/entgql/internal/todoplugin/ent/runtime" + + "entgo.io/ent/dialect/sql/schema" +) + +type ( + // TestingT is the interface that is shared between + // testing.T and testing.B and used by enttest. + TestingT interface { + FailNow() + Error(...interface{}) + } + + // Option configures client creation. + Option func(*options) + + options struct { + opts []ent.Option + migrateOpts []schema.MigrateOption + } +) + +// WithOptions forwards options to client creation. +func WithOptions(opts ...ent.Option) Option { + return func(o *options) { + o.opts = append(o.opts, opts...) + } +} + +// WithMigrateOptions forwards options to auto migration. +func WithMigrateOptions(opts ...schema.MigrateOption) Option { + return func(o *options) { + o.migrateOpts = append(o.migrateOpts, opts...) + } +} + +func newOptions(opts []Option) *options { + o := &options{} + for _, opt := range opts { + opt(o) + } + return o +} + +// Open calls ent.Open and auto-run migration. +func Open(t TestingT, driverName, dataSourceName string, opts ...Option) *ent.Client { + o := newOptions(opts) + c, err := ent.Open(driverName, dataSourceName, o.opts...) + if err != nil { + t.Error(err) + t.FailNow() + } + if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil { + t.Error(err) + t.FailNow() + } + return c +} + +// NewClient calls ent.NewClient and auto-run migration. +func NewClient(t TestingT, opts ...Option) *ent.Client { + o := newOptions(opts) + c := ent.NewClient(o.opts...) + if err := c.Schema.Create(context.Background(), o.migrateOpts...); err != nil { + t.Error(err) + t.FailNow() + } + return c +} diff --git a/entgql/internal/todoplugin/ent/gql_collection.go b/entgql/internal/todoplugin/ent/gql_collection.go new file mode 100644 index 000000000..37f9b568d --- /dev/null +++ b/entgql/internal/todoplugin/ent/gql_collection.go @@ -0,0 +1,71 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + + "github.com/99designs/gqlgen/graphql" +) + +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (c *CategoryQuery) CollectFields(ctx context.Context, satisfies ...string) *CategoryQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + c = c.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return c +} + +func (c *CategoryQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *CategoryQuery { + return c +} + +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (t *TodoQuery) CollectFields(ctx context.Context, satisfies ...string) *TodoQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + t = t.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return t +} + +func (t *TodoQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *TodoQuery { + for _, field := range graphql.CollectFields(ctx, field.Selections, satisfies) { + switch field.Name { + case "children": + t = t.WithChildren(func(query *TodoQuery) { + query.collectField(ctx, field) + }) + case "parent": + t = t.WithParent(func(query *TodoQuery) { + query.collectField(ctx, field) + }) + } + } + return t +} + +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (u *UserQuery) CollectFields(ctx context.Context, satisfies ...string) *UserQuery { + if fc := graphql.GetFieldContext(ctx); fc != nil { + u = u.collectField(graphql.GetOperationContext(ctx), fc.Field, satisfies...) + } + return u +} + +func (u *UserQuery) collectField(ctx *graphql.OperationContext, field graphql.CollectedField, satisfies ...string) *UserQuery { + return u +} diff --git a/entgql/internal/todoplugin/ent/gql_edge.go b/entgql/internal/todoplugin/ent/gql_edge.go new file mode 100644 index 000000000..cfa35b72c --- /dev/null +++ b/entgql/internal/todoplugin/ent/gql_edge.go @@ -0,0 +1,43 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import "context" + +func (c *Category) Todos(ctx context.Context) ([]*Todo, error) { + result, err := c.Edges.TodosOrErr() + if IsNotLoaded(err) { + result, err = c.QueryTodos().All(ctx) + } + return result, err +} + +func (t *Todo) Parent(ctx context.Context) (*Todo, error) { + result, err := t.Edges.ParentOrErr() + if IsNotLoaded(err) { + result, err = t.QueryParent().Only(ctx) + } + return result, MaskNotFound(err) +} + +func (t *Todo) Children(ctx context.Context) ([]*Todo, error) { + result, err := t.Edges.ChildrenOrErr() + if IsNotLoaded(err) { + result, err = t.QueryChildren().All(ctx) + } + return result, err +} diff --git a/entgql/internal/todoplugin/ent/gql_node.go b/entgql/internal/todoplugin/ent/gql_node.go new file mode 100644 index 000000000..1981401c6 --- /dev/null +++ b/entgql/internal/todoplugin/ent/gql_node.go @@ -0,0 +1,510 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "encoding/json" + "fmt" + "sync" + "sync/atomic" + + "entgo.io/contrib/entgql" + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/schema" + "github.com/99designs/gqlgen/graphql" + "github.com/hashicorp/go-multierror" + "golang.org/x/sync/semaphore" +) + +// Noder wraps the basic Node method. +type Noder interface { + Node(context.Context) (*Node, error) +} + +// Node in the graph. +type Node struct { + ID int `json:"id,omitempty"` // node id. + Type string `json:"type,omitempty"` // node type. + Fields []*Field `json:"fields,omitempty"` // node fields. + Edges []*Edge `json:"edges,omitempty"` // node edges. +} + +// Field of a node. +type Field struct { + Type string `json:"type,omitempty"` // field type. + Name string `json:"name,omitempty"` // field name (as in struct). + Value string `json:"value,omitempty"` // stringified value. +} + +// Edges between two nodes. +type Edge struct { + Type string `json:"type,omitempty"` // edge type. + Name string `json:"name,omitempty"` // edge name. + IDs []int `json:"ids,omitempty"` // node ids (where this edge point to). +} + +func (c *Category) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: c.ID, + Type: "Category", + Fields: make([]*Field, 6), + Edges: make([]*Edge, 1), + } + var buf []byte + if buf, err = json.Marshal(c.Text); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "string", + Name: "text", + Value: string(buf), + } + if buf, err = json.Marshal(c.Status); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "category.Status", + Name: "status", + Value: string(buf), + } + if buf, err = json.Marshal(c.Config); err != nil { + return nil, err + } + node.Fields[2] = &Field{ + Type: "*schematype.CategoryConfig", + Name: "config", + Value: string(buf), + } + if buf, err = json.Marshal(c.Duration); err != nil { + return nil, err + } + node.Fields[3] = &Field{ + Type: "time.Duration", + Name: "duration", + Value: string(buf), + } + if buf, err = json.Marshal(c.Count); err != nil { + return nil, err + } + node.Fields[4] = &Field{ + Type: "uint64", + Name: "count", + Value: string(buf), + } + if buf, err = json.Marshal(c.Strings); err != nil { + return nil, err + } + node.Fields[5] = &Field{ + Type: "[]string", + Name: "strings", + Value: string(buf), + } + node.Edges[0] = &Edge{ + Type: "Todo", + Name: "todos", + } + err = c.QueryTodos(). + Select(todo.FieldID). + Scan(ctx, &node.Edges[0].IDs) + if err != nil { + return nil, err + } + return node, nil +} + +func (t *Todo) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: t.ID, + Type: "Todo", + Fields: make([]*Field, 5), + Edges: make([]*Edge, 2), + } + var buf []byte + if buf, err = json.Marshal(t.CreatedAt); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "time.Time", + Name: "created_at", + Value: string(buf), + } + if buf, err = json.Marshal(t.VisibilityStatus); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "todo.VisibilityStatus", + Name: "visibility_status", + Value: string(buf), + } + if buf, err = json.Marshal(t.Status); err != nil { + return nil, err + } + node.Fields[2] = &Field{ + Type: "todo.Status", + Name: "status", + Value: string(buf), + } + if buf, err = json.Marshal(t.Priority); err != nil { + return nil, err + } + node.Fields[3] = &Field{ + Type: "int", + Name: "priority", + Value: string(buf), + } + if buf, err = json.Marshal(t.Text); err != nil { + return nil, err + } + node.Fields[4] = &Field{ + Type: "string", + Name: "text", + Value: string(buf), + } + node.Edges[0] = &Edge{ + Type: "Todo", + Name: "parent", + } + err = t.QueryParent(). + Select(todo.FieldID). + Scan(ctx, &node.Edges[0].IDs) + if err != nil { + return nil, err + } + node.Edges[1] = &Edge{ + Type: "Todo", + Name: "children", + } + err = t.QueryChildren(). + Select(todo.FieldID). + Scan(ctx, &node.Edges[1].IDs) + if err != nil { + return nil, err + } + return node, nil +} + +func (u *User) Node(ctx context.Context) (node *Node, err error) { + node = &Node{ + ID: u.ID, + Type: "User", + Fields: make([]*Field, 4), + Edges: make([]*Edge, 0), + } + var buf []byte + if buf, err = json.Marshal(u.Username); err != nil { + return nil, err + } + node.Fields[0] = &Field{ + Type: "string", + Name: "username", + Value: string(buf), + } + if buf, err = json.Marshal(u.Age); err != nil { + return nil, err + } + node.Fields[1] = &Field{ + Type: "int", + Name: "age", + Value: string(buf), + } + if buf, err = json.Marshal(u.Amount); err != nil { + return nil, err + } + node.Fields[2] = &Field{ + Type: "schema.Amount", + Name: "amount", + Value: string(buf), + } + if buf, err = json.Marshal(u.Role); err != nil { + return nil, err + } + node.Fields[3] = &Field{ + Type: "role.Role", + Name: "role", + Value: string(buf), + } + return node, nil +} + +func (c *Client) Node(ctx context.Context, id int) (*Node, error) { + n, err := c.Noder(ctx, id) + if err != nil { + return nil, err + } + return n.Node(ctx) +} + +var errNodeInvalidID = &NotFoundError{"node"} + +// NodeOption allows configuring the Noder execution using functional options. +type NodeOption func(*nodeOptions) + +// WithNodeType sets the node Type resolver function (i.e. the table to query). +// If was not provided, the table will be derived from the universal-id +// configuration as described in: https://entgo.io/docs/migrate/#universal-ids. +func WithNodeType(f func(context.Context, int) (string, error)) NodeOption { + return func(o *nodeOptions) { + o.nodeType = f + } +} + +// WithFixedNodeType sets the Type of the node to a fixed value. +func WithFixedNodeType(t string) NodeOption { + return WithNodeType(func(context.Context, int) (string, error) { + return t, nil + }) +} + +type nodeOptions struct { + nodeType func(context.Context, int) (string, error) +} + +func (c *Client) newNodeOpts(opts []NodeOption) *nodeOptions { + nopts := &nodeOptions{} + for _, opt := range opts { + opt(nopts) + } + if nopts.nodeType == nil { + nopts.nodeType = func(ctx context.Context, id int) (string, error) { + return c.tables.nodeType(ctx, c.driver, id) + } + } + return nopts +} + +// Noder returns a Node by its id. If the NodeType was not provided, it will +// be derived from the id value according to the universal-id configuration. +// +// c.Noder(ctx, id) +// c.Noder(ctx, id, ent.WithNodeType(pet.Table)) +// +func (c *Client) Noder(ctx context.Context, id int, opts ...NodeOption) (_ Noder, err error) { + defer func() { + if IsNotFound(err) { + err = multierror.Append(err, entgql.ErrNodeNotFound(id)) + } + }() + table, err := c.newNodeOpts(opts).nodeType(ctx, id) + if err != nil { + return nil, err + } + return c.noder(ctx, table, id) +} + +func (c *Client) noder(ctx context.Context, table string, id int) (Noder, error) { + switch table { + case category.Table: + n, err := c.Category.Query(). + Where(category.ID(id)). + CollectFields(ctx, "Category"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil + case todo.Table: + n, err := c.Todo.Query(). + Where(todo.ID(id)). + CollectFields(ctx, "Todo"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil + case user.Table: + n, err := c.User.Query(). + Where(user.ID(id)). + CollectFields(ctx, "User"). + Only(ctx) + if err != nil { + return nil, err + } + return n, nil + default: + return nil, fmt.Errorf("cannot resolve noder from table %q: %w", table, errNodeInvalidID) + } +} + +func (c *Client) Noders(ctx context.Context, ids []int, opts ...NodeOption) ([]Noder, error) { + switch len(ids) { + case 1: + noder, err := c.Noder(ctx, ids[0], opts...) + if err != nil { + return nil, err + } + return []Noder{noder}, nil + case 0: + return []Noder{}, nil + } + + noders := make([]Noder, len(ids)) + errors := make([]error, len(ids)) + tables := make(map[string][]int) + id2idx := make(map[int][]int, len(ids)) + nopts := c.newNodeOpts(opts) + for i, id := range ids { + table, err := nopts.nodeType(ctx, id) + if err != nil { + errors[i] = err + continue + } + tables[table] = append(tables[table], id) + id2idx[id] = append(id2idx[id], i) + } + + for table, ids := range tables { + nodes, err := c.noders(ctx, table, ids) + if err != nil { + for _, id := range ids { + for _, idx := range id2idx[id] { + errors[idx] = err + } + } + } else { + for i, id := range ids { + for _, idx := range id2idx[id] { + noders[idx] = nodes[i] + } + } + } + } + + for i, id := range ids { + if errors[i] == nil { + if noders[i] != nil { + continue + } + errors[i] = entgql.ErrNodeNotFound(id) + } else if IsNotFound(errors[i]) { + errors[i] = multierror.Append(errors[i], entgql.ErrNodeNotFound(id)) + } + ctx := graphql.WithPathContext(ctx, + graphql.NewPathWithIndex(i), + ) + graphql.AddError(ctx, errors[i]) + } + return noders, nil +} + +func (c *Client) noders(ctx context.Context, table string, ids []int) ([]Noder, error) { + noders := make([]Noder, len(ids)) + idmap := make(map[int][]*Noder, len(ids)) + for i, id := range ids { + idmap[id] = append(idmap[id], &noders[i]) + } + switch table { + case category.Table: + nodes, err := c.Category.Query(). + Where(category.IDIn(ids...)). + CollectFields(ctx, "Category"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } + case todo.Table: + nodes, err := c.Todo.Query(). + Where(todo.IDIn(ids...)). + CollectFields(ctx, "Todo"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } + case user.Table: + nodes, err := c.User.Query(). + Where(user.IDIn(ids...)). + CollectFields(ctx, "User"). + All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } + default: + return nil, fmt.Errorf("cannot resolve noders from table %q: %w", table, errNodeInvalidID) + } + return noders, nil +} + +type tables struct { + once sync.Once + sem *semaphore.Weighted + value atomic.Value +} + +func (t *tables) nodeType(ctx context.Context, drv dialect.Driver, id int) (string, error) { + tables, err := t.Load(ctx, drv) + if err != nil { + return "", err + } + idx := int(id / (1<<32 - 1)) + if idx < 0 || idx >= len(tables) { + return "", fmt.Errorf("cannot resolve table from id %v: %w", id, errNodeInvalidID) + } + return tables[idx], nil +} + +func (t *tables) Load(ctx context.Context, drv dialect.Driver) ([]string, error) { + if tables := t.value.Load(); tables != nil { + return tables.([]string), nil + } + t.once.Do(func() { t.sem = semaphore.NewWeighted(1) }) + if err := t.sem.Acquire(ctx, 1); err != nil { + return nil, err + } + defer t.sem.Release(1) + if tables := t.value.Load(); tables != nil { + return tables.([]string), nil + } + tables, err := t.load(ctx, drv) + if err == nil { + t.value.Store(tables) + } + return tables, err +} + +func (*tables) load(ctx context.Context, drv dialect.Driver) ([]string, error) { + rows := &sql.Rows{} + query, args := sql.Dialect(drv.Dialect()). + Select("type"). + From(sql.Table(schema.TypeTable)). + OrderBy(sql.Asc("id")). + Query() + if err := drv.Query(ctx, query, args, rows); err != nil { + return nil, err + } + defer rows.Close() + var tables []string + return tables, sql.ScanSlice(rows, &tables) +} diff --git a/entgql/internal/todoplugin/ent/gql_pagination.go b/entgql/internal/todoplugin/ent/gql_pagination.go new file mode 100644 index 000000000..803221416 --- /dev/null +++ b/entgql/internal/todoplugin/ent/gql_pagination.go @@ -0,0 +1,1086 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "encoding/base64" + "errors" + "fmt" + "io" + "strconv" + "strings" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect/sql" + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/errcode" + "github.com/vektah/gqlparser/v2/gqlerror" + "github.com/vmihailenco/msgpack/v5" +) + +// OrderDirection defines the directions in which to order a list of items. +type OrderDirection string + +const ( + // OrderDirectionAsc specifies an ascending order. + OrderDirectionAsc OrderDirection = "ASC" + // OrderDirectionDesc specifies a descending order. + OrderDirectionDesc OrderDirection = "DESC" +) + +// Validate the order direction value. +func (o OrderDirection) Validate() error { + if o != OrderDirectionAsc && o != OrderDirectionDesc { + return fmt.Errorf("%s is not a valid OrderDirection", o) + } + return nil +} + +// String implements fmt.Stringer interface. +func (o OrderDirection) String() string { + return string(o) +} + +// MarshalGQL implements graphql.Marshaler interface. +func (o OrderDirection) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(o.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (o *OrderDirection) UnmarshalGQL(val interface{}) error { + str, ok := val.(string) + if !ok { + return fmt.Errorf("order direction %T must be a string", val) + } + *o = OrderDirection(str) + return o.Validate() +} + +func (o OrderDirection) reverse() OrderDirection { + if o == OrderDirectionDesc { + return OrderDirectionAsc + } + return OrderDirectionDesc +} + +func (o OrderDirection) orderFunc(field string) OrderFunc { + if o == OrderDirectionDesc { + return Desc(field) + } + return Asc(field) +} + +func cursorsToPredicates(direction OrderDirection, after, before *Cursor, field, idField string) []func(s *sql.Selector) { + var predicates []func(s *sql.Selector) + if after != nil { + if after.Value != nil { + var predicate func([]string, ...interface{}) *sql.Predicate + if direction == OrderDirectionAsc { + predicate = sql.CompositeGT + } else { + predicate = sql.CompositeLT + } + predicates = append(predicates, func(s *sql.Selector) { + s.Where(predicate( + s.Columns(field, idField), + after.Value, after.ID, + )) + }) + } else { + var predicate func(string, interface{}) *sql.Predicate + if direction == OrderDirectionAsc { + predicate = sql.GT + } else { + predicate = sql.LT + } + predicates = append(predicates, func(s *sql.Selector) { + s.Where(predicate( + s.C(idField), + after.ID, + )) + }) + } + } + if before != nil { + if before.Value != nil { + var predicate func([]string, ...interface{}) *sql.Predicate + if direction == OrderDirectionAsc { + predicate = sql.CompositeLT + } else { + predicate = sql.CompositeGT + } + predicates = append(predicates, func(s *sql.Selector) { + s.Where(predicate( + s.Columns(field, idField), + before.Value, before.ID, + )) + }) + } else { + var predicate func(string, interface{}) *sql.Predicate + if direction == OrderDirectionAsc { + predicate = sql.LT + } else { + predicate = sql.GT + } + predicates = append(predicates, func(s *sql.Selector) { + s.Where(predicate( + s.C(idField), + before.ID, + )) + }) + } + } + return predicates +} + +// PageInfo of a connection type. +type PageInfo struct { + HasNextPage bool `json:"hasNextPage"` + HasPreviousPage bool `json:"hasPreviousPage"` + StartCursor *Cursor `json:"startCursor"` + EndCursor *Cursor `json:"endCursor"` +} + +// Cursor of an edge type. +type Cursor struct { + ID int `msgpack:"i"` + Value Value `msgpack:"v,omitempty"` +} + +// MarshalGQL implements graphql.Marshaler interface. +func (c Cursor) MarshalGQL(w io.Writer) { + quote := []byte{'"'} + w.Write(quote) + defer w.Write(quote) + wc := base64.NewEncoder(base64.RawStdEncoding, w) + defer wc.Close() + _ = msgpack.NewEncoder(wc).Encode(c) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (c *Cursor) UnmarshalGQL(v interface{}) error { + s, ok := v.(string) + if !ok { + return fmt.Errorf("%T is not a string", v) + } + if err := msgpack.NewDecoder( + base64.NewDecoder( + base64.RawStdEncoding, + strings.NewReader(s), + ), + ).Decode(c); err != nil { + return fmt.Errorf("cannot decode cursor: %w", err) + } + return nil +} + +const errInvalidPagination = "INVALID_PAGINATION" + +func validateFirstLast(first, last *int) (err *gqlerror.Error) { + switch { + case first != nil && last != nil: + err = &gqlerror.Error{ + Message: "Passing both `first` and `last` to paginate a connection is not supported.", + } + case first != nil && *first < 0: + err = &gqlerror.Error{ + Message: "`first` on a connection cannot be less than zero.", + } + errcode.Set(err, errInvalidPagination) + case last != nil && *last < 0: + err = &gqlerror.Error{ + Message: "`last` on a connection cannot be less than zero.", + } + errcode.Set(err, errInvalidPagination) + } + return err +} + +func getCollectedField(ctx context.Context, path ...string) *graphql.CollectedField { + fc := graphql.GetFieldContext(ctx) + if fc == nil { + return nil + } + oc := graphql.GetOperationContext(ctx) + field := fc.Field + +walk: + for _, name := range path { + for _, f := range graphql.CollectFields(oc, field.Selections, nil) { + if f.Name == name { + field = f + continue walk + } + } + return nil + } + return &field +} + +func hasCollectedField(ctx context.Context, path ...string) bool { + if graphql.GetFieldContext(ctx) == nil { + return true + } + return getCollectedField(ctx, path...) != nil +} + +const ( + edgesField = "edges" + nodeField = "node" + pageInfoField = "pageInfo" + totalCountField = "totalCount" +) + +// CategoryEdge is the edge representation of Category. +type CategoryEdge struct { + Node *Category `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// CategoryConnection is the connection containing edges to Category. +type CategoryConnection struct { + Edges []*CategoryEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// CategoryPaginateOption enables pagination customization. +type CategoryPaginateOption func(*categoryPager) error + +// WithCategoryOrder configures pagination ordering. +func WithCategoryOrder(order *CategoryOrder) CategoryPaginateOption { + if order == nil { + order = DefaultCategoryOrder + } + o := *order + return func(pager *categoryPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultCategoryOrder.Field + } + pager.order = &o + return nil + } +} + +// WithCategoryFilter configures pagination filter. +func WithCategoryFilter(filter func(*CategoryQuery) (*CategoryQuery, error)) CategoryPaginateOption { + return func(pager *categoryPager) error { + if filter == nil { + return errors.New("CategoryQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type categoryPager struct { + order *CategoryOrder + filter func(*CategoryQuery) (*CategoryQuery, error) +} + +func newCategoryPager(opts []CategoryPaginateOption) (*categoryPager, error) { + pager := &categoryPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultCategoryOrder + } + return pager, nil +} + +func (p *categoryPager) applyFilter(query *CategoryQuery) (*CategoryQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *categoryPager) toCursor(c *Category) Cursor { + return p.order.Field.toCursor(c) +} + +func (p *categoryPager) applyCursors(query *CategoryQuery, after, before *Cursor) *CategoryQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultCategoryOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *categoryPager) applyOrder(query *CategoryQuery, reverse bool) *CategoryQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultCategoryOrder.Field { + query = query.Order(direction.orderFunc(DefaultCategoryOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to Category. +func (c *CategoryQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...CategoryPaginateOption, +) (*CategoryConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newCategoryPager(opts) + if err != nil { + return nil, err + } + + if c, err = pager.applyFilter(c); err != nil { + return nil, err + } + + conn := &CategoryConnection{Edges: []*CategoryEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := c.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := c.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + c = pager.applyCursors(c, after, before) + c = pager.applyOrder(c, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + c = c.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + c = c.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := c.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *Category + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *Category { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *Category { + return nodes[i] + } + } + + conn.Edges = make([]*CategoryEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &CategoryEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +var ( + // CategoryOrderFieldText orders Category by text. + CategoryOrderFieldText = &CategoryOrderField{ + field: category.FieldText, + toCursor: func(c *Category) Cursor { + return Cursor{ + ID: c.ID, + Value: c.Text, + } + }, + } + // CategoryOrderFieldDuration orders Category by duration. + CategoryOrderFieldDuration = &CategoryOrderField{ + field: category.FieldDuration, + toCursor: func(c *Category) Cursor { + return Cursor{ + ID: c.ID, + Value: c.Duration, + } + }, + } +) + +// String implement fmt.Stringer interface. +func (f CategoryOrderField) String() string { + var str string + switch f.field { + case category.FieldText: + str = "TEXT" + case category.FieldDuration: + str = "DURATION" + } + return str +} + +// MarshalGQL implements graphql.Marshaler interface. +func (f CategoryOrderField) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(f.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (f *CategoryOrderField) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("CategoryOrderField %T must be a string", v) + } + switch str { + case "TEXT": + *f = *CategoryOrderFieldText + case "DURATION": + *f = *CategoryOrderFieldDuration + default: + return fmt.Errorf("%s is not a valid CategoryOrderField", str) + } + return nil +} + +// CategoryOrderField defines the ordering field of Category. +type CategoryOrderField struct { + field string + toCursor func(*Category) Cursor +} + +// CategoryOrder defines the ordering of Category. +type CategoryOrder struct { + Direction OrderDirection `json:"direction"` + Field *CategoryOrderField `json:"field"` +} + +// DefaultCategoryOrder is the default ordering of Category. +var DefaultCategoryOrder = &CategoryOrder{ + Direction: OrderDirectionAsc, + Field: &CategoryOrderField{ + field: category.FieldID, + toCursor: func(c *Category) Cursor { + return Cursor{ID: c.ID} + }, + }, +} + +// ToEdge converts Category into CategoryEdge. +func (c *Category) ToEdge(order *CategoryOrder) *CategoryEdge { + if order == nil { + order = DefaultCategoryOrder + } + return &CategoryEdge{ + Node: c, + Cursor: order.Field.toCursor(c), + } +} + +// TodoEdge is the edge representation of Todo. +type TodoEdge struct { + Node *Todo `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// TodoConnection is the connection containing edges to Todo. +type TodoConnection struct { + Edges []*TodoEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// TodoPaginateOption enables pagination customization. +type TodoPaginateOption func(*todoPager) error + +// WithTodoOrder configures pagination ordering. +func WithTodoOrder(order *TodoOrder) TodoPaginateOption { + if order == nil { + order = DefaultTodoOrder + } + o := *order + return func(pager *todoPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultTodoOrder.Field + } + pager.order = &o + return nil + } +} + +// WithTodoFilter configures pagination filter. +func WithTodoFilter(filter func(*TodoQuery) (*TodoQuery, error)) TodoPaginateOption { + return func(pager *todoPager) error { + if filter == nil { + return errors.New("TodoQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type todoPager struct { + order *TodoOrder + filter func(*TodoQuery) (*TodoQuery, error) +} + +func newTodoPager(opts []TodoPaginateOption) (*todoPager, error) { + pager := &todoPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultTodoOrder + } + return pager, nil +} + +func (p *todoPager) applyFilter(query *TodoQuery) (*TodoQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *todoPager) toCursor(t *Todo) Cursor { + return p.order.Field.toCursor(t) +} + +func (p *todoPager) applyCursors(query *TodoQuery, after, before *Cursor) *TodoQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultTodoOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *todoPager) applyOrder(query *TodoQuery, reverse bool) *TodoQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultTodoOrder.Field { + query = query.Order(direction.orderFunc(DefaultTodoOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to Todo. +func (t *TodoQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...TodoPaginateOption, +) (*TodoConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newTodoPager(opts) + if err != nil { + return nil, err + } + + if t, err = pager.applyFilter(t); err != nil { + return nil, err + } + + conn := &TodoConnection{Edges: []*TodoEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := t.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := t.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + t = pager.applyCursors(t, after, before) + t = pager.applyOrder(t, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + t = t.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + t = t.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := t.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *Todo + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *Todo { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *Todo { + return nodes[i] + } + } + + conn.Edges = make([]*TodoEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &TodoEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +var ( + // TodoOrderFieldCreatedAt orders Todo by created_at. + TodoOrderFieldCreatedAt = &TodoOrderField{ + field: todo.FieldCreatedAt, + toCursor: func(t *Todo) Cursor { + return Cursor{ + ID: t.ID, + Value: t.CreatedAt, + } + }, + } + // TodoOrderFieldVisibilityStatus orders Todo by visibility_status. + TodoOrderFieldVisibilityStatus = &TodoOrderField{ + field: todo.FieldVisibilityStatus, + toCursor: func(t *Todo) Cursor { + return Cursor{ + ID: t.ID, + Value: t.VisibilityStatus, + } + }, + } + // TodoOrderFieldStatus orders Todo by status. + TodoOrderFieldStatus = &TodoOrderField{ + field: todo.FieldStatus, + toCursor: func(t *Todo) Cursor { + return Cursor{ + ID: t.ID, + Value: t.Status, + } + }, + } + // TodoOrderFieldPriority orders Todo by priority. + TodoOrderFieldPriority = &TodoOrderField{ + field: todo.FieldPriority, + toCursor: func(t *Todo) Cursor { + return Cursor{ + ID: t.ID, + Value: t.Priority, + } + }, + } + // TodoOrderFieldText orders Todo by text. + TodoOrderFieldText = &TodoOrderField{ + field: todo.FieldText, + toCursor: func(t *Todo) Cursor { + return Cursor{ + ID: t.ID, + Value: t.Text, + } + }, + } +) + +// String implement fmt.Stringer interface. +func (f TodoOrderField) String() string { + var str string + switch f.field { + case todo.FieldCreatedAt: + str = "CREATED_AT" + case todo.FieldVisibilityStatus: + str = "VISIBILITY_STATUS" + case todo.FieldStatus: + str = "STATUS" + case todo.FieldPriority: + str = "PRIORITY" + case todo.FieldText: + str = "TEXT" + } + return str +} + +// MarshalGQL implements graphql.Marshaler interface. +func (f TodoOrderField) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(f.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (f *TodoOrderField) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("TodoOrderField %T must be a string", v) + } + switch str { + case "CREATED_AT": + *f = *TodoOrderFieldCreatedAt + case "VISIBILITY_STATUS": + *f = *TodoOrderFieldVisibilityStatus + case "STATUS": + *f = *TodoOrderFieldStatus + case "PRIORITY": + *f = *TodoOrderFieldPriority + case "TEXT": + *f = *TodoOrderFieldText + default: + return fmt.Errorf("%s is not a valid TodoOrderField", str) + } + return nil +} + +// TodoOrderField defines the ordering field of Todo. +type TodoOrderField struct { + field string + toCursor func(*Todo) Cursor +} + +// TodoOrder defines the ordering of Todo. +type TodoOrder struct { + Direction OrderDirection `json:"direction"` + Field *TodoOrderField `json:"field"` +} + +// DefaultTodoOrder is the default ordering of Todo. +var DefaultTodoOrder = &TodoOrder{ + Direction: OrderDirectionAsc, + Field: &TodoOrderField{ + field: todo.FieldID, + toCursor: func(t *Todo) Cursor { + return Cursor{ID: t.ID} + }, + }, +} + +// ToEdge converts Todo into TodoEdge. +func (t *Todo) ToEdge(order *TodoOrder) *TodoEdge { + if order == nil { + order = DefaultTodoOrder + } + return &TodoEdge{ + Node: t, + Cursor: order.Field.toCursor(t), + } +} + +// UserEdge is the edge representation of User. +type UserEdge struct { + Node *User `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// UserConnection is the connection containing edges to User. +type UserConnection struct { + Edges []*UserEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// UserPaginateOption enables pagination customization. +type UserPaginateOption func(*userPager) error + +// WithUserOrder configures pagination ordering. +func WithUserOrder(order *UserOrder) UserPaginateOption { + if order == nil { + order = DefaultUserOrder + } + o := *order + return func(pager *userPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultUserOrder.Field + } + pager.order = &o + return nil + } +} + +// WithUserFilter configures pagination filter. +func WithUserFilter(filter func(*UserQuery) (*UserQuery, error)) UserPaginateOption { + return func(pager *userPager) error { + if filter == nil { + return errors.New("UserQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type userPager struct { + order *UserOrder + filter func(*UserQuery) (*UserQuery, error) +} + +func newUserPager(opts []UserPaginateOption) (*userPager, error) { + pager := &userPager{} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultUserOrder + } + return pager, nil +} + +func (p *userPager) applyFilter(query *UserQuery) (*UserQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *userPager) toCursor(u *User) Cursor { + return p.order.Field.toCursor(u) +} + +func (p *userPager) applyCursors(query *UserQuery, after, before *Cursor) *UserQuery { + for _, predicate := range cursorsToPredicates( + p.order.Direction, after, before, + p.order.Field.field, DefaultUserOrder.Field.field, + ) { + query = query.Where(predicate) + } + return query +} + +func (p *userPager) applyOrder(query *UserQuery, reverse bool) *UserQuery { + direction := p.order.Direction + if reverse { + direction = direction.reverse() + } + query = query.Order(direction.orderFunc(p.order.Field.field)) + if p.order.Field != DefaultUserOrder.Field { + query = query.Order(direction.orderFunc(DefaultUserOrder.Field.field)) + } + return query +} + +// Paginate executes the query and returns a relay based cursor connection to User. +func (u *UserQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...UserPaginateOption, +) (*UserConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newUserPager(opts) + if err != nil { + return nil, err + } + + if u, err = pager.applyFilter(u); err != nil { + return nil, err + } + + conn := &UserConnection{Edges: []*UserEdge{}} + if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { + if hasCollectedField(ctx, totalCountField) || + hasCollectedField(ctx, pageInfoField) { + count, err := u.Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + conn.PageInfo.HasNextPage = first != nil && count > 0 + conn.PageInfo.HasPreviousPage = last != nil && count > 0 + } + return conn, nil + } + + if (after != nil || first != nil || before != nil || last != nil) && hasCollectedField(ctx, totalCountField) { + count, err := u.Clone().Count(ctx) + if err != nil { + return nil, err + } + conn.TotalCount = count + } + + u = pager.applyCursors(u, after, before) + u = pager.applyOrder(u, last != nil) + var limit int + if first != nil { + limit = *first + 1 + } else if last != nil { + limit = *last + 1 + } + if limit > 0 { + u = u.Limit(limit) + } + + if field := getCollectedField(ctx, edgesField, nodeField); field != nil { + u = u.collectField(graphql.GetOperationContext(ctx), *field) + } + + nodes, err := u.All(ctx) + if err != nil || len(nodes) == 0 { + return conn, err + } + + if len(nodes) == limit { + conn.PageInfo.HasNextPage = first != nil + conn.PageInfo.HasPreviousPage = last != nil + nodes = nodes[:len(nodes)-1] + } + + var nodeAt func(int) *User + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *User { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *User { + return nodes[i] + } + } + + conn.Edges = make([]*UserEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + conn.Edges[i] = &UserEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + + conn.PageInfo.StartCursor = &conn.Edges[0].Cursor + conn.PageInfo.EndCursor = &conn.Edges[len(conn.Edges)-1].Cursor + if conn.TotalCount == 0 { + conn.TotalCount = len(nodes) + } + + return conn, nil +} + +// UserOrderField defines the ordering field of User. +type UserOrderField struct { + field string + toCursor func(*User) Cursor +} + +// UserOrder defines the ordering of User. +type UserOrder struct { + Direction OrderDirection `json:"direction"` + Field *UserOrderField `json:"field"` +} + +// DefaultUserOrder is the default ordering of User. +var DefaultUserOrder = &UserOrder{ + Direction: OrderDirectionAsc, + Field: &UserOrderField{ + field: user.FieldID, + toCursor: func(u *User) Cursor { + return Cursor{ID: u.ID} + }, + }, +} + +// ToEdge converts User into UserEdge. +func (u *User) ToEdge(order *UserOrder) *UserEdge { + if order == nil { + order = DefaultUserOrder + } + return &UserEdge{ + Node: u, + Cursor: order.Field.toCursor(u), + } +} diff --git a/entgql/internal/todoplugin/ent/gql_transaction.go b/entgql/internal/todoplugin/ent/gql_transaction.go new file mode 100644 index 000000000..c830f09f2 --- /dev/null +++ b/entgql/internal/todoplugin/ent/gql_transaction.go @@ -0,0 +1,44 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "errors" +) + +// OpenTx opens a transaction and returns a transactional +// context along with the created transaction. +func (c *Client) OpenTx(ctx context.Context) (context.Context, driver.Tx, error) { + tx, err := c.Tx(ctx) + if err != nil { + return nil, nil, err + } + ctx = NewTxContext(ctx, tx) + ctx = NewContext(ctx, tx.Client()) + return ctx, tx, nil +} + +// OpenTxFromContext open transactions from client stored in context. +func OpenTxFromContext(ctx context.Context) (context.Context, driver.Tx, error) { + client := FromContext(ctx) + if client == nil { + return nil, nil, errors.New("no client attached to context") + } + return client.OpenTx(ctx) +} diff --git a/entgql/internal/todoplugin/ent/gql_where_input.go b/entgql/internal/todoplugin/ent/gql_where_input.go new file mode 100644 index 000000000..2bf9d0fd7 --- /dev/null +++ b/entgql/internal/todoplugin/ent/gql_where_input.go @@ -0,0 +1,925 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" +) + +// CategoryWhereInput represents a where input for filtering Category queries. +type CategoryWhereInput struct { + Not *CategoryWhereInput `json:"not,omitempty"` + Or []*CategoryWhereInput `json:"or,omitempty"` + And []*CategoryWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "text" field predicates. + Text *string `json:"text,omitempty"` + TextNEQ *string `json:"textNEQ,omitempty"` + TextIn []string `json:"textIn,omitempty"` + TextNotIn []string `json:"textNotIn,omitempty"` + TextGT *string `json:"textGT,omitempty"` + TextGTE *string `json:"textGTE,omitempty"` + TextLT *string `json:"textLT,omitempty"` + TextLTE *string `json:"textLTE,omitempty"` + TextContains *string `json:"textContains,omitempty"` + TextHasPrefix *string `json:"textHasPrefix,omitempty"` + TextHasSuffix *string `json:"textHasSuffix,omitempty"` + TextEqualFold *string `json:"textEqualFold,omitempty"` + TextContainsFold *string `json:"textContainsFold,omitempty"` + + // "status" field predicates. + Status *category.Status `json:"status,omitempty"` + StatusNEQ *category.Status `json:"statusNEQ,omitempty"` + StatusIn []category.Status `json:"statusIn,omitempty"` + StatusNotIn []category.Status `json:"statusNotIn,omitempty"` + + // "config" field predicates. + Config *schematype.CategoryConfig `json:"config,omitempty"` + ConfigNEQ *schematype.CategoryConfig `json:"configNEQ,omitempty"` + ConfigIn []*schematype.CategoryConfig `json:"configIn,omitempty"` + ConfigNotIn []*schematype.CategoryConfig `json:"configNotIn,omitempty"` + ConfigGT *schematype.CategoryConfig `json:"configGT,omitempty"` + ConfigGTE *schematype.CategoryConfig `json:"configGTE,omitempty"` + ConfigLT *schematype.CategoryConfig `json:"configLT,omitempty"` + ConfigLTE *schematype.CategoryConfig `json:"configLTE,omitempty"` + ConfigIsNil bool `json:"configIsNil,omitempty"` + ConfigNotNil bool `json:"configNotNil,omitempty"` + + // "duration" field predicates. + Duration *time.Duration `json:"duration,omitempty"` + DurationNEQ *time.Duration `json:"durationNEQ,omitempty"` + DurationIn []time.Duration `json:"durationIn,omitempty"` + DurationNotIn []time.Duration `json:"durationNotIn,omitempty"` + DurationGT *time.Duration `json:"durationGT,omitempty"` + DurationGTE *time.Duration `json:"durationGTE,omitempty"` + DurationLT *time.Duration `json:"durationLT,omitempty"` + DurationLTE *time.Duration `json:"durationLTE,omitempty"` + DurationIsNil bool `json:"durationIsNil,omitempty"` + DurationNotNil bool `json:"durationNotNil,omitempty"` + + // "count" field predicates. + Count *uint64 `json:"count,omitempty"` + CountNEQ *uint64 `json:"countNEQ,omitempty"` + CountIn []uint64 `json:"countIn,omitempty"` + CountNotIn []uint64 `json:"countNotIn,omitempty"` + CountGT *uint64 `json:"countGT,omitempty"` + CountGTE *uint64 `json:"countGTE,omitempty"` + CountLT *uint64 `json:"countLT,omitempty"` + CountLTE *uint64 `json:"countLTE,omitempty"` + CountIsNil bool `json:"countIsNil,omitempty"` + CountNotNil bool `json:"countNotNil,omitempty"` + + // "todos" edge predicates. + HasTodos *bool `json:"hasTodos,omitempty"` + HasTodosWith []*TodoWhereInput `json:"hasTodosWith,omitempty"` +} + +// Filter applies the CategoryWhereInput filter on the CategoryQuery builder. +func (i *CategoryWhereInput) Filter(q *CategoryQuery) (*CategoryQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering categories. +// An error is returned if the input is empty or invalid. +func (i *CategoryWhereInput) P() (predicate.Category, error) { + var predicates []predicate.Category + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, category.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.Category, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, category.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.Category, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, category.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, category.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, category.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, category.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, category.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, category.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, category.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, category.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, category.IDLTE(*i.IDLTE)) + } + if i.Text != nil { + predicates = append(predicates, category.TextEQ(*i.Text)) + } + if i.TextNEQ != nil { + predicates = append(predicates, category.TextNEQ(*i.TextNEQ)) + } + if len(i.TextIn) > 0 { + predicates = append(predicates, category.TextIn(i.TextIn...)) + } + if len(i.TextNotIn) > 0 { + predicates = append(predicates, category.TextNotIn(i.TextNotIn...)) + } + if i.TextGT != nil { + predicates = append(predicates, category.TextGT(*i.TextGT)) + } + if i.TextGTE != nil { + predicates = append(predicates, category.TextGTE(*i.TextGTE)) + } + if i.TextLT != nil { + predicates = append(predicates, category.TextLT(*i.TextLT)) + } + if i.TextLTE != nil { + predicates = append(predicates, category.TextLTE(*i.TextLTE)) + } + if i.TextContains != nil { + predicates = append(predicates, category.TextContains(*i.TextContains)) + } + if i.TextHasPrefix != nil { + predicates = append(predicates, category.TextHasPrefix(*i.TextHasPrefix)) + } + if i.TextHasSuffix != nil { + predicates = append(predicates, category.TextHasSuffix(*i.TextHasSuffix)) + } + if i.TextEqualFold != nil { + predicates = append(predicates, category.TextEqualFold(*i.TextEqualFold)) + } + if i.TextContainsFold != nil { + predicates = append(predicates, category.TextContainsFold(*i.TextContainsFold)) + } + if i.Status != nil { + predicates = append(predicates, category.StatusEQ(*i.Status)) + } + if i.StatusNEQ != nil { + predicates = append(predicates, category.StatusNEQ(*i.StatusNEQ)) + } + if len(i.StatusIn) > 0 { + predicates = append(predicates, category.StatusIn(i.StatusIn...)) + } + if len(i.StatusNotIn) > 0 { + predicates = append(predicates, category.StatusNotIn(i.StatusNotIn...)) + } + if i.Config != nil { + predicates = append(predicates, category.ConfigEQ(i.Config)) + } + if i.ConfigNEQ != nil { + predicates = append(predicates, category.ConfigNEQ(i.ConfigNEQ)) + } + if len(i.ConfigIn) > 0 { + predicates = append(predicates, category.ConfigIn(i.ConfigIn...)) + } + if len(i.ConfigNotIn) > 0 { + predicates = append(predicates, category.ConfigNotIn(i.ConfigNotIn...)) + } + if i.ConfigGT != nil { + predicates = append(predicates, category.ConfigGT(i.ConfigGT)) + } + if i.ConfigGTE != nil { + predicates = append(predicates, category.ConfigGTE(i.ConfigGTE)) + } + if i.ConfigLT != nil { + predicates = append(predicates, category.ConfigLT(i.ConfigLT)) + } + if i.ConfigLTE != nil { + predicates = append(predicates, category.ConfigLTE(i.ConfigLTE)) + } + if i.ConfigIsNil { + predicates = append(predicates, category.ConfigIsNil()) + } + if i.ConfigNotNil { + predicates = append(predicates, category.ConfigNotNil()) + } + if i.Duration != nil { + predicates = append(predicates, category.DurationEQ(*i.Duration)) + } + if i.DurationNEQ != nil { + predicates = append(predicates, category.DurationNEQ(*i.DurationNEQ)) + } + if len(i.DurationIn) > 0 { + predicates = append(predicates, category.DurationIn(i.DurationIn...)) + } + if len(i.DurationNotIn) > 0 { + predicates = append(predicates, category.DurationNotIn(i.DurationNotIn...)) + } + if i.DurationGT != nil { + predicates = append(predicates, category.DurationGT(*i.DurationGT)) + } + if i.DurationGTE != nil { + predicates = append(predicates, category.DurationGTE(*i.DurationGTE)) + } + if i.DurationLT != nil { + predicates = append(predicates, category.DurationLT(*i.DurationLT)) + } + if i.DurationLTE != nil { + predicates = append(predicates, category.DurationLTE(*i.DurationLTE)) + } + if i.DurationIsNil { + predicates = append(predicates, category.DurationIsNil()) + } + if i.DurationNotNil { + predicates = append(predicates, category.DurationNotNil()) + } + if i.Count != nil { + predicates = append(predicates, category.CountEQ(*i.Count)) + } + if i.CountNEQ != nil { + predicates = append(predicates, category.CountNEQ(*i.CountNEQ)) + } + if len(i.CountIn) > 0 { + predicates = append(predicates, category.CountIn(i.CountIn...)) + } + if len(i.CountNotIn) > 0 { + predicates = append(predicates, category.CountNotIn(i.CountNotIn...)) + } + if i.CountGT != nil { + predicates = append(predicates, category.CountGT(*i.CountGT)) + } + if i.CountGTE != nil { + predicates = append(predicates, category.CountGTE(*i.CountGTE)) + } + if i.CountLT != nil { + predicates = append(predicates, category.CountLT(*i.CountLT)) + } + if i.CountLTE != nil { + predicates = append(predicates, category.CountLTE(*i.CountLTE)) + } + if i.CountIsNil { + predicates = append(predicates, category.CountIsNil()) + } + if i.CountNotNil { + predicates = append(predicates, category.CountNotNil()) + } + + if i.HasTodos != nil { + p := category.HasTodos() + if !*i.HasTodos { + p = category.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasTodosWith) > 0 { + with := make([]predicate.Todo, 0, len(i.HasTodosWith)) + for _, w := range i.HasTodosWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, category.HasTodosWith(with...)) + } + switch len(predicates) { + case 0: + return nil, fmt.Errorf("empty predicate CategoryWhereInput") + case 1: + return predicates[0], nil + default: + return category.And(predicates...), nil + } +} + +// TodoWhereInput represents a where input for filtering Todo queries. +type TodoWhereInput struct { + Not *TodoWhereInput `json:"not,omitempty"` + Or []*TodoWhereInput `json:"or,omitempty"` + And []*TodoWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "created_at" field predicates. + CreatedAt *time.Time `json:"createdAt,omitempty"` + CreatedAtNEQ *time.Time `json:"createdAtNEQ,omitempty"` + CreatedAtIn []time.Time `json:"createdAtIn,omitempty"` + CreatedAtNotIn []time.Time `json:"createdAtNotIn,omitempty"` + CreatedAtGT *time.Time `json:"createdAtGT,omitempty"` + CreatedAtGTE *time.Time `json:"createdAtGTE,omitempty"` + CreatedAtLT *time.Time `json:"createdAtLT,omitempty"` + CreatedAtLTE *time.Time `json:"createdAtLTE,omitempty"` + + // "visibility_status" field predicates. + VisibilityStatus *todo.VisibilityStatus `json:"visibilityStatus,omitempty"` + VisibilityStatusNEQ *todo.VisibilityStatus `json:"visibilityStatusNEQ,omitempty"` + VisibilityStatusIn []todo.VisibilityStatus `json:"visibilityStatusIn,omitempty"` + VisibilityStatusNotIn []todo.VisibilityStatus `json:"visibilityStatusNotIn,omitempty"` + + // "status" field predicates. + Status *todo.Status `json:"status,omitempty"` + StatusNEQ *todo.Status `json:"statusNEQ,omitempty"` + StatusIn []todo.Status `json:"statusIn,omitempty"` + StatusNotIn []todo.Status `json:"statusNotIn,omitempty"` + + // "priority" field predicates. + Priority *int `json:"priority,omitempty"` + PriorityNEQ *int `json:"priorityNEQ,omitempty"` + PriorityIn []int `json:"priorityIn,omitempty"` + PriorityNotIn []int `json:"priorityNotIn,omitempty"` + PriorityGT *int `json:"priorityGT,omitempty"` + PriorityGTE *int `json:"priorityGTE,omitempty"` + PriorityLT *int `json:"priorityLT,omitempty"` + PriorityLTE *int `json:"priorityLTE,omitempty"` + + // "text" field predicates. + Text *string `json:"text,omitempty"` + TextNEQ *string `json:"textNEQ,omitempty"` + TextIn []string `json:"textIn,omitempty"` + TextNotIn []string `json:"textNotIn,omitempty"` + TextGT *string `json:"textGT,omitempty"` + TextGTE *string `json:"textGTE,omitempty"` + TextLT *string `json:"textLT,omitempty"` + TextLTE *string `json:"textLTE,omitempty"` + TextContains *string `json:"textContains,omitempty"` + TextHasPrefix *string `json:"textHasPrefix,omitempty"` + TextHasSuffix *string `json:"textHasSuffix,omitempty"` + TextEqualFold *string `json:"textEqualFold,omitempty"` + TextContainsFold *string `json:"textContainsFold,omitempty"` + + // "parent" edge predicates. + HasParent *bool `json:"hasParent,omitempty"` + HasParentWith []*TodoWhereInput `json:"hasParentWith,omitempty"` + + // "children" edge predicates. + HasChildren *bool `json:"hasChildren,omitempty"` + HasChildrenWith []*TodoWhereInput `json:"hasChildrenWith,omitempty"` +} + +// Filter applies the TodoWhereInput filter on the TodoQuery builder. +func (i *TodoWhereInput) Filter(q *TodoQuery) (*TodoQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering todos. +// An error is returned if the input is empty or invalid. +func (i *TodoWhereInput) P() (predicate.Todo, error) { + var predicates []predicate.Todo + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, todo.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.Todo, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, todo.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.Todo, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, todo.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, todo.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, todo.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, todo.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, todo.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, todo.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, todo.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, todo.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, todo.IDLTE(*i.IDLTE)) + } + if i.CreatedAt != nil { + predicates = append(predicates, todo.CreatedAtEQ(*i.CreatedAt)) + } + if i.CreatedAtNEQ != nil { + predicates = append(predicates, todo.CreatedAtNEQ(*i.CreatedAtNEQ)) + } + if len(i.CreatedAtIn) > 0 { + predicates = append(predicates, todo.CreatedAtIn(i.CreatedAtIn...)) + } + if len(i.CreatedAtNotIn) > 0 { + predicates = append(predicates, todo.CreatedAtNotIn(i.CreatedAtNotIn...)) + } + if i.CreatedAtGT != nil { + predicates = append(predicates, todo.CreatedAtGT(*i.CreatedAtGT)) + } + if i.CreatedAtGTE != nil { + predicates = append(predicates, todo.CreatedAtGTE(*i.CreatedAtGTE)) + } + if i.CreatedAtLT != nil { + predicates = append(predicates, todo.CreatedAtLT(*i.CreatedAtLT)) + } + if i.CreatedAtLTE != nil { + predicates = append(predicates, todo.CreatedAtLTE(*i.CreatedAtLTE)) + } + if i.VisibilityStatus != nil { + predicates = append(predicates, todo.VisibilityStatusEQ(*i.VisibilityStatus)) + } + if i.VisibilityStatusNEQ != nil { + predicates = append(predicates, todo.VisibilityStatusNEQ(*i.VisibilityStatusNEQ)) + } + if len(i.VisibilityStatusIn) > 0 { + predicates = append(predicates, todo.VisibilityStatusIn(i.VisibilityStatusIn...)) + } + if len(i.VisibilityStatusNotIn) > 0 { + predicates = append(predicates, todo.VisibilityStatusNotIn(i.VisibilityStatusNotIn...)) + } + if i.Status != nil { + predicates = append(predicates, todo.StatusEQ(*i.Status)) + } + if i.StatusNEQ != nil { + predicates = append(predicates, todo.StatusNEQ(*i.StatusNEQ)) + } + if len(i.StatusIn) > 0 { + predicates = append(predicates, todo.StatusIn(i.StatusIn...)) + } + if len(i.StatusNotIn) > 0 { + predicates = append(predicates, todo.StatusNotIn(i.StatusNotIn...)) + } + if i.Priority != nil { + predicates = append(predicates, todo.PriorityEQ(*i.Priority)) + } + if i.PriorityNEQ != nil { + predicates = append(predicates, todo.PriorityNEQ(*i.PriorityNEQ)) + } + if len(i.PriorityIn) > 0 { + predicates = append(predicates, todo.PriorityIn(i.PriorityIn...)) + } + if len(i.PriorityNotIn) > 0 { + predicates = append(predicates, todo.PriorityNotIn(i.PriorityNotIn...)) + } + if i.PriorityGT != nil { + predicates = append(predicates, todo.PriorityGT(*i.PriorityGT)) + } + if i.PriorityGTE != nil { + predicates = append(predicates, todo.PriorityGTE(*i.PriorityGTE)) + } + if i.PriorityLT != nil { + predicates = append(predicates, todo.PriorityLT(*i.PriorityLT)) + } + if i.PriorityLTE != nil { + predicates = append(predicates, todo.PriorityLTE(*i.PriorityLTE)) + } + if i.Text != nil { + predicates = append(predicates, todo.TextEQ(*i.Text)) + } + if i.TextNEQ != nil { + predicates = append(predicates, todo.TextNEQ(*i.TextNEQ)) + } + if len(i.TextIn) > 0 { + predicates = append(predicates, todo.TextIn(i.TextIn...)) + } + if len(i.TextNotIn) > 0 { + predicates = append(predicates, todo.TextNotIn(i.TextNotIn...)) + } + if i.TextGT != nil { + predicates = append(predicates, todo.TextGT(*i.TextGT)) + } + if i.TextGTE != nil { + predicates = append(predicates, todo.TextGTE(*i.TextGTE)) + } + if i.TextLT != nil { + predicates = append(predicates, todo.TextLT(*i.TextLT)) + } + if i.TextLTE != nil { + predicates = append(predicates, todo.TextLTE(*i.TextLTE)) + } + if i.TextContains != nil { + predicates = append(predicates, todo.TextContains(*i.TextContains)) + } + if i.TextHasPrefix != nil { + predicates = append(predicates, todo.TextHasPrefix(*i.TextHasPrefix)) + } + if i.TextHasSuffix != nil { + predicates = append(predicates, todo.TextHasSuffix(*i.TextHasSuffix)) + } + if i.TextEqualFold != nil { + predicates = append(predicates, todo.TextEqualFold(*i.TextEqualFold)) + } + if i.TextContainsFold != nil { + predicates = append(predicates, todo.TextContainsFold(*i.TextContainsFold)) + } + + if i.HasParent != nil { + p := todo.HasParent() + if !*i.HasParent { + p = todo.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasParentWith) > 0 { + with := make([]predicate.Todo, 0, len(i.HasParentWith)) + for _, w := range i.HasParentWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, todo.HasParentWith(with...)) + } + if i.HasChildren != nil { + p := todo.HasChildren() + if !*i.HasChildren { + p = todo.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasChildrenWith) > 0 { + with := make([]predicate.Todo, 0, len(i.HasChildrenWith)) + for _, w := range i.HasChildrenWith { + p, err := w.P() + if err != nil { + return nil, err + } + with = append(with, p) + } + predicates = append(predicates, todo.HasChildrenWith(with...)) + } + switch len(predicates) { + case 0: + return nil, fmt.Errorf("empty predicate TodoWhereInput") + case 1: + return predicates[0], nil + default: + return todo.And(predicates...), nil + } +} + +// UserWhereInput represents a where input for filtering User queries. +type UserWhereInput struct { + Not *UserWhereInput `json:"not,omitempty"` + Or []*UserWhereInput `json:"or,omitempty"` + And []*UserWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int `json:"id,omitempty"` + IDNEQ *int `json:"idNEQ,omitempty"` + IDIn []int `json:"idIn,omitempty"` + IDNotIn []int `json:"idNotIn,omitempty"` + IDGT *int `json:"idGT,omitempty"` + IDGTE *int `json:"idGTE,omitempty"` + IDLT *int `json:"idLT,omitempty"` + IDLTE *int `json:"idLTE,omitempty"` + + // "username" field predicates. + Username *string `json:"username,omitempty"` + UsernameNEQ *string `json:"usernameNEQ,omitempty"` + UsernameIn []string `json:"usernameIn,omitempty"` + UsernameNotIn []string `json:"usernameNotIn,omitempty"` + UsernameGT *string `json:"usernameGT,omitempty"` + UsernameGTE *string `json:"usernameGTE,omitempty"` + UsernameLT *string `json:"usernameLT,omitempty"` + UsernameLTE *string `json:"usernameLTE,omitempty"` + UsernameContains *string `json:"usernameContains,omitempty"` + UsernameHasPrefix *string `json:"usernameHasPrefix,omitempty"` + UsernameHasSuffix *string `json:"usernameHasSuffix,omitempty"` + UsernameEqualFold *string `json:"usernameEqualFold,omitempty"` + UsernameContainsFold *string `json:"usernameContainsFold,omitempty"` + + // "age" field predicates. + Age *int `json:"age,omitempty"` + AgeNEQ *int `json:"ageNEQ,omitempty"` + AgeIn []int `json:"ageIn,omitempty"` + AgeNotIn []int `json:"ageNotIn,omitempty"` + AgeGT *int `json:"ageGT,omitempty"` + AgeGTE *int `json:"ageGTE,omitempty"` + AgeLT *int `json:"ageLT,omitempty"` + AgeLTE *int `json:"ageLTE,omitempty"` + + // "amount" field predicates. + Amount *schema.Amount `json:"amount,omitempty"` + AmountNEQ *schema.Amount `json:"amountNEQ,omitempty"` + AmountIn []schema.Amount `json:"amountIn,omitempty"` + AmountNotIn []schema.Amount `json:"amountNotIn,omitempty"` + AmountGT *schema.Amount `json:"amountGT,omitempty"` + AmountGTE *schema.Amount `json:"amountGTE,omitempty"` + AmountLT *schema.Amount `json:"amountLT,omitempty"` + AmountLTE *schema.Amount `json:"amountLTE,omitempty"` + + // "role" field predicates. + Role *role.Role `json:"role,omitempty"` + RoleNEQ *role.Role `json:"roleNEQ,omitempty"` + RoleIn []role.Role `json:"roleIn,omitempty"` + RoleNotIn []role.Role `json:"roleNotIn,omitempty"` +} + +// Filter applies the UserWhereInput filter on the UserQuery builder. +func (i *UserWhereInput) Filter(q *UserQuery) (*UserQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + return nil, err + } + return q.Where(p), nil +} + +// P returns a predicate for filtering users. +// An error is returned if the input is empty or invalid. +func (i *UserWhereInput) P() (predicate.User, error) { + var predicates []predicate.User + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, err + } + predicates = append(predicates, user.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.User, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, err + } + or = append(or, p) + } + predicates = append(predicates, user.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, err + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.User, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, err + } + and = append(and, p) + } + predicates = append(predicates, user.And(and...)) + } + if i.ID != nil { + predicates = append(predicates, user.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, user.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, user.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, user.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, user.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, user.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, user.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, user.IDLTE(*i.IDLTE)) + } + if i.Username != nil { + predicates = append(predicates, user.UsernameEQ(*i.Username)) + } + if i.UsernameNEQ != nil { + predicates = append(predicates, user.UsernameNEQ(*i.UsernameNEQ)) + } + if len(i.UsernameIn) > 0 { + predicates = append(predicates, user.UsernameIn(i.UsernameIn...)) + } + if len(i.UsernameNotIn) > 0 { + predicates = append(predicates, user.UsernameNotIn(i.UsernameNotIn...)) + } + if i.UsernameGT != nil { + predicates = append(predicates, user.UsernameGT(*i.UsernameGT)) + } + if i.UsernameGTE != nil { + predicates = append(predicates, user.UsernameGTE(*i.UsernameGTE)) + } + if i.UsernameLT != nil { + predicates = append(predicates, user.UsernameLT(*i.UsernameLT)) + } + if i.UsernameLTE != nil { + predicates = append(predicates, user.UsernameLTE(*i.UsernameLTE)) + } + if i.UsernameContains != nil { + predicates = append(predicates, user.UsernameContains(*i.UsernameContains)) + } + if i.UsernameHasPrefix != nil { + predicates = append(predicates, user.UsernameHasPrefix(*i.UsernameHasPrefix)) + } + if i.UsernameHasSuffix != nil { + predicates = append(predicates, user.UsernameHasSuffix(*i.UsernameHasSuffix)) + } + if i.UsernameEqualFold != nil { + predicates = append(predicates, user.UsernameEqualFold(*i.UsernameEqualFold)) + } + if i.UsernameContainsFold != nil { + predicates = append(predicates, user.UsernameContainsFold(*i.UsernameContainsFold)) + } + if i.Age != nil { + predicates = append(predicates, user.AgeEQ(*i.Age)) + } + if i.AgeNEQ != nil { + predicates = append(predicates, user.AgeNEQ(*i.AgeNEQ)) + } + if len(i.AgeIn) > 0 { + predicates = append(predicates, user.AgeIn(i.AgeIn...)) + } + if len(i.AgeNotIn) > 0 { + predicates = append(predicates, user.AgeNotIn(i.AgeNotIn...)) + } + if i.AgeGT != nil { + predicates = append(predicates, user.AgeGT(*i.AgeGT)) + } + if i.AgeGTE != nil { + predicates = append(predicates, user.AgeGTE(*i.AgeGTE)) + } + if i.AgeLT != nil { + predicates = append(predicates, user.AgeLT(*i.AgeLT)) + } + if i.AgeLTE != nil { + predicates = append(predicates, user.AgeLTE(*i.AgeLTE)) + } + if i.Amount != nil { + predicates = append(predicates, user.AmountEQ(*i.Amount)) + } + if i.AmountNEQ != nil { + predicates = append(predicates, user.AmountNEQ(*i.AmountNEQ)) + } + if len(i.AmountIn) > 0 { + predicates = append(predicates, user.AmountIn(i.AmountIn...)) + } + if len(i.AmountNotIn) > 0 { + predicates = append(predicates, user.AmountNotIn(i.AmountNotIn...)) + } + if i.AmountGT != nil { + predicates = append(predicates, user.AmountGT(*i.AmountGT)) + } + if i.AmountGTE != nil { + predicates = append(predicates, user.AmountGTE(*i.AmountGTE)) + } + if i.AmountLT != nil { + predicates = append(predicates, user.AmountLT(*i.AmountLT)) + } + if i.AmountLTE != nil { + predicates = append(predicates, user.AmountLTE(*i.AmountLTE)) + } + if i.Role != nil { + predicates = append(predicates, user.RoleEQ(*i.Role)) + } + if i.RoleNEQ != nil { + predicates = append(predicates, user.RoleNEQ(*i.RoleNEQ)) + } + if len(i.RoleIn) > 0 { + predicates = append(predicates, user.RoleIn(i.RoleIn...)) + } + if len(i.RoleNotIn) > 0 { + predicates = append(predicates, user.RoleNotIn(i.RoleNotIn...)) + } + + switch len(predicates) { + case 0: + return nil, fmt.Errorf("empty predicate UserWhereInput") + case 1: + return predicates[0], nil + default: + return user.And(predicates...), nil + } +} diff --git a/entgql/internal/todoplugin/ent/hook/hook.go b/entgql/internal/todoplugin/ent/hook/hook.go new file mode 100644 index 000000000..fc6bb8aaa --- /dev/null +++ b/entgql/internal/todoplugin/ent/hook/hook.go @@ -0,0 +1,244 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package hook + +import ( + "context" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent" +) + +// The CategoryFunc type is an adapter to allow the use of ordinary +// function as Category mutator. +type CategoryFunc func(context.Context, *ent.CategoryMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f CategoryFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.CategoryMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.CategoryMutation", m) + } + return f(ctx, mv) +} + +// The TodoFunc type is an adapter to allow the use of ordinary +// function as Todo mutator. +type TodoFunc func(context.Context, *ent.TodoMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f TodoFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.TodoMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.TodoMutation", m) + } + return f(ctx, mv) +} + +// The UserFunc type is an adapter to allow the use of ordinary +// function as User mutator. +type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f UserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + mv, ok := m.(*ent.UserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m) + } + return f(ctx, mv) +} + +// Condition is a hook condition function. +type Condition func(context.Context, ent.Mutation) bool + +// And groups conditions with the AND operator. +func And(first, second Condition, rest ...Condition) Condition { + return func(ctx context.Context, m ent.Mutation) bool { + if !first(ctx, m) || !second(ctx, m) { + return false + } + for _, cond := range rest { + if !cond(ctx, m) { + return false + } + } + return true + } +} + +// Or groups conditions with the OR operator. +func Or(first, second Condition, rest ...Condition) Condition { + return func(ctx context.Context, m ent.Mutation) bool { + if first(ctx, m) || second(ctx, m) { + return true + } + for _, cond := range rest { + if cond(ctx, m) { + return true + } + } + return false + } +} + +// Not negates a given condition. +func Not(cond Condition) Condition { + return func(ctx context.Context, m ent.Mutation) bool { + return !cond(ctx, m) + } +} + +// HasOp is a condition testing mutation operation. +func HasOp(op ent.Op) Condition { + return func(_ context.Context, m ent.Mutation) bool { + return m.Op().Is(op) + } +} + +// HasAddedFields is a condition validating `.AddedField` on fields. +func HasAddedFields(field string, fields ...string) Condition { + return func(_ context.Context, m ent.Mutation) bool { + if _, exists := m.AddedField(field); !exists { + return false + } + for _, field := range fields { + if _, exists := m.AddedField(field); !exists { + return false + } + } + return true + } +} + +// HasClearedFields is a condition validating `.FieldCleared` on fields. +func HasClearedFields(field string, fields ...string) Condition { + return func(_ context.Context, m ent.Mutation) bool { + if exists := m.FieldCleared(field); !exists { + return false + } + for _, field := range fields { + if exists := m.FieldCleared(field); !exists { + return false + } + } + return true + } +} + +// HasFields is a condition validating `.Field` on fields. +func HasFields(field string, fields ...string) Condition { + return func(_ context.Context, m ent.Mutation) bool { + if _, exists := m.Field(field); !exists { + return false + } + for _, field := range fields { + if _, exists := m.Field(field); !exists { + return false + } + } + return true + } +} + +// If executes the given hook under condition. +// +// hook.If(ComputeAverage, And(HasFields(...), HasAddedFields(...))) +// +func If(hk ent.Hook, cond Condition) ent.Hook { + return func(next ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if cond(ctx, m) { + return hk(next).Mutate(ctx, m) + } + return next.Mutate(ctx, m) + }) + } +} + +// On executes the given hook only for the given operation. +// +// hook.On(Log, ent.Delete|ent.Create) +// +func On(hk ent.Hook, op ent.Op) ent.Hook { + return If(hk, HasOp(op)) +} + +// Unless skips the given hook only for the given operation. +// +// hook.Unless(Log, ent.Update|ent.UpdateOne) +// +func Unless(hk ent.Hook, op ent.Op) ent.Hook { + return If(hk, Not(HasOp(op))) +} + +// FixedError is a hook returning a fixed error. +func FixedError(err error) ent.Hook { + return func(ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(context.Context, ent.Mutation) (ent.Value, error) { + return nil, err + }) + } +} + +// Reject returns a hook that rejects all operations that match op. +// +// func (T) Hooks() []ent.Hook { +// return []ent.Hook{ +// Reject(ent.Delete|ent.Update), +// } +// } +// +func Reject(op ent.Op) ent.Hook { + hk := FixedError(fmt.Errorf("%s operation is not allowed", op)) + return On(hk, op) +} + +// Chain acts as a list of hooks and is effectively immutable. +// Once created, it will always hold the same set of hooks in the same order. +type Chain struct { + hooks []ent.Hook +} + +// NewChain creates a new chain of hooks. +func NewChain(hooks ...ent.Hook) Chain { + return Chain{append([]ent.Hook(nil), hooks...)} +} + +// Hook chains the list of hooks and returns the final hook. +func (c Chain) Hook() ent.Hook { + return func(mutator ent.Mutator) ent.Mutator { + for i := len(c.hooks) - 1; i >= 0; i-- { + mutator = c.hooks[i](mutator) + } + return mutator + } +} + +// Append extends a chain, adding the specified hook +// as the last ones in the mutation flow. +func (c Chain) Append(hooks ...ent.Hook) Chain { + newHooks := make([]ent.Hook, 0, len(c.hooks)+len(hooks)) + newHooks = append(newHooks, c.hooks...) + newHooks = append(newHooks, hooks...) + return Chain{newHooks} +} + +// Extend extends a chain, adding the specified chain +// as the last ones in the mutation flow. +func (c Chain) Extend(chain Chain) Chain { + return c.Append(chain.hooks...) +} diff --git a/entgql/internal/todoplugin/ent/migrate/migrate.go b/entgql/internal/todoplugin/ent/migrate/migrate.go new file mode 100644 index 000000000..afa51a91d --- /dev/null +++ b/entgql/internal/todoplugin/ent/migrate/migrate.go @@ -0,0 +1,85 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package migrate + +import ( + "context" + "fmt" + "io" + + "entgo.io/ent/dialect" + "entgo.io/ent/dialect/sql/schema" +) + +var ( + // WithGlobalUniqueID sets the universal ids options to the migration. + // If this option is enabled, ent migration will allocate a 1<<32 range + // for the ids of each entity (table). + // Note that this option cannot be applied on tables that already exist. + WithGlobalUniqueID = schema.WithGlobalUniqueID + // WithDropColumn sets the drop column option to the migration. + // If this option is enabled, ent migration will drop old columns + // that were used for both fields and edges. This defaults to false. + WithDropColumn = schema.WithDropColumn + // WithDropIndex sets the drop index option to the migration. + // If this option is enabled, ent migration will drop old indexes + // that were defined in the schema. This defaults to false. + // Note that unique constraints are defined using `UNIQUE INDEX`, + // and therefore, it's recommended to enable this option to get more + // flexibility in the schema changes. + WithDropIndex = schema.WithDropIndex + // WithFixture sets the foreign-key renaming option to the migration when upgrading + // ent from v0.1.0 (issue-#285). Defaults to false. + WithFixture = schema.WithFixture + // WithForeignKeys enables creating foreign-key in schema DDL. This defaults to true. + WithForeignKeys = schema.WithForeignKeys +) + +// Schema is the API for creating, migrating and dropping a schema. +type Schema struct { + drv dialect.Driver +} + +// NewSchema creates a new schema client. +func NewSchema(drv dialect.Driver) *Schema { return &Schema{drv: drv} } + +// Create creates all schema resources. +func (s *Schema) Create(ctx context.Context, opts ...schema.MigrateOption) error { + migrate, err := schema.NewMigrate(s.drv, opts...) + if err != nil { + return fmt.Errorf("ent/migrate: %w", err) + } + return migrate.Create(ctx, Tables...) +} + +// WriteTo writes the schema changes to w instead of running them against the database. +// +// if err := client.Schema.WriteTo(context.Background(), os.Stdout); err != nil { +// log.Fatal(err) +// } +// +func (s *Schema) WriteTo(ctx context.Context, w io.Writer, opts ...schema.MigrateOption) error { + drv := &schema.WriteDriver{ + Writer: w, + Driver: s.drv, + } + migrate, err := schema.NewMigrate(drv, opts...) + if err != nil { + return fmt.Errorf("ent/migrate: %w", err) + } + return migrate.Create(ctx, Tables...) +} diff --git a/entgql/internal/todoplugin/ent/migrate/schema.go b/entgql/internal/todoplugin/ent/migrate/schema.go new file mode 100644 index 000000000..29a612287 --- /dev/null +++ b/entgql/internal/todoplugin/ent/migrate/schema.go @@ -0,0 +1,97 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package migrate + +import ( + "entgo.io/ent/dialect/sql/schema" + "entgo.io/ent/schema/field" +) + +var ( + // CategoriesColumns holds the columns for the "categories" table. + CategoriesColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "text", Type: field.TypeString, Size: 2147483647}, + {Name: "status", Type: field.TypeEnum, Enums: []string{"ENABLED", "DISABLED"}}, + {Name: "config", Type: field.TypeOther, Nullable: true, SchemaType: map[string]string{"sqlite3": "json"}}, + {Name: "duration", Type: field.TypeInt64, Nullable: true}, + {Name: "count", Type: field.TypeUint64, Nullable: true}, + {Name: "strings", Type: field.TypeJSON, Nullable: true}, + } + // CategoriesTable holds the schema information for the "categories" table. + CategoriesTable = &schema.Table{ + Name: "categories", + Columns: CategoriesColumns, + PrimaryKey: []*schema.Column{CategoriesColumns[0]}, + } + // TodosColumns holds the columns for the "todos" table. + TodosColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "created_at", Type: field.TypeTime}, + {Name: "visibility_status", Type: field.TypeEnum, Enums: []string{"LISTING", "HIDDEN"}, Default: "HIDDEN"}, + {Name: "status", Type: field.TypeEnum, Enums: []string{"IN_PROGRESS", "COMPLETED"}}, + {Name: "priority", Type: field.TypeInt, Default: 0}, + {Name: "text", Type: field.TypeString, Size: 2147483647}, + {Name: "category_todos", Type: field.TypeInt, Nullable: true}, + {Name: "todo_children", Type: field.TypeInt, Nullable: true}, + } + // TodosTable holds the schema information for the "todos" table. + TodosTable = &schema.Table{ + Name: "todos", + Columns: TodosColumns, + PrimaryKey: []*schema.Column{TodosColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "todos_categories_todos", + Columns: []*schema.Column{TodosColumns[6]}, + RefColumns: []*schema.Column{CategoriesColumns[0]}, + OnDelete: schema.SetNull, + }, + { + Symbol: "todos_todos_children", + Columns: []*schema.Column{TodosColumns[7]}, + RefColumns: []*schema.Column{TodosColumns[0]}, + OnDelete: schema.SetNull, + }, + }, + } + // UsersColumns holds the columns for the "users" table. + UsersColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt, Increment: true}, + {Name: "username", Type: field.TypeString}, + {Name: "age", Type: field.TypeInt}, + {Name: "amount", Type: field.TypeFloat64}, + {Name: "role", Type: field.TypeEnum, Enums: []string{"ADMIN", "USER", "UNKNOWN"}}, + } + // UsersTable holds the schema information for the "users" table. + UsersTable = &schema.Table{ + Name: "users", + Columns: UsersColumns, + PrimaryKey: []*schema.Column{UsersColumns[0]}, + } + // Tables holds all the tables in the schema. + Tables = []*schema.Table{ + CategoriesTable, + TodosTable, + UsersTable, + } +) + +func init() { + TodosTable.ForeignKeys[0].RefTable = CategoriesTable + TodosTable.ForeignKeys[1].RefTable = TodosTable +} diff --git a/entgql/internal/todoplugin/ent/mutation.go b/entgql/internal/todoplugin/ent/mutation.go new file mode 100644 index 000000000..30ba87cfe --- /dev/null +++ b/entgql/internal/todoplugin/ent/mutation.go @@ -0,0 +1,2130 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + + "entgo.io/ent" +) + +const ( + // Operation types. + OpCreate = ent.OpCreate + OpDelete = ent.OpDelete + OpDeleteOne = ent.OpDeleteOne + OpUpdate = ent.OpUpdate + OpUpdateOne = ent.OpUpdateOne + + // Node types. + TypeCategory = "Category" + TypeTodo = "Todo" + TypeUser = "User" +) + +// CategoryMutation represents an operation that mutates the Category nodes in the graph. +type CategoryMutation struct { + config + op Op + typ string + id *int + text *string + status *category.Status + _config **schematype.CategoryConfig + duration *time.Duration + addduration *time.Duration + count *uint64 + addcount *int64 + strings *[]string + clearedFields map[string]struct{} + todos map[int]struct{} + removedtodos map[int]struct{} + clearedtodos bool + done bool + oldValue func(context.Context) (*Category, error) + predicates []predicate.Category +} + +var _ ent.Mutation = (*CategoryMutation)(nil) + +// categoryOption allows management of the mutation configuration using functional options. +type categoryOption func(*CategoryMutation) + +// newCategoryMutation creates new mutation for the Category entity. +func newCategoryMutation(c config, op Op, opts ...categoryOption) *CategoryMutation { + m := &CategoryMutation{ + config: c, + op: op, + typ: TypeCategory, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withCategoryID sets the ID field of the mutation. +func withCategoryID(id int) categoryOption { + return func(m *CategoryMutation) { + var ( + err error + once sync.Once + value *Category + ) + m.oldValue = func(ctx context.Context) (*Category, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Category.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withCategory sets the old Category of the mutation. +func withCategory(node *Category) categoryOption { + return func(m *CategoryMutation) { + m.oldValue = func(context.Context) (*Category, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m CategoryMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m CategoryMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *CategoryMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *CategoryMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Category.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetText sets the "text" field. +func (m *CategoryMutation) SetText(s string) { + m.text = &s +} + +// Text returns the value of the "text" field in the mutation. +func (m *CategoryMutation) Text() (r string, exists bool) { + v := m.text + if v == nil { + return + } + return *v, true +} + +// OldText returns the old "text" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldText(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldText is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldText requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldText: %w", err) + } + return oldValue.Text, nil +} + +// ResetText resets all changes to the "text" field. +func (m *CategoryMutation) ResetText() { + m.text = nil +} + +// SetStatus sets the "status" field. +func (m *CategoryMutation) SetStatus(c category.Status) { + m.status = &c +} + +// Status returns the value of the "status" field in the mutation. +func (m *CategoryMutation) Status() (r category.Status, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldStatus(ctx context.Context) (v category.Status, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ResetStatus resets all changes to the "status" field. +func (m *CategoryMutation) ResetStatus() { + m.status = nil +} + +// SetConfig sets the "config" field. +func (m *CategoryMutation) SetConfig(sc *schematype.CategoryConfig) { + m._config = &sc +} + +// Config returns the value of the "config" field in the mutation. +func (m *CategoryMutation) Config() (r *schematype.CategoryConfig, exists bool) { + v := m._config + if v == nil { + return + } + return *v, true +} + +// OldConfig returns the old "config" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldConfig(ctx context.Context) (v *schematype.CategoryConfig, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldConfig is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldConfig requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldConfig: %w", err) + } + return oldValue.Config, nil +} + +// ClearConfig clears the value of the "config" field. +func (m *CategoryMutation) ClearConfig() { + m._config = nil + m.clearedFields[category.FieldConfig] = struct{}{} +} + +// ConfigCleared returns if the "config" field was cleared in this mutation. +func (m *CategoryMutation) ConfigCleared() bool { + _, ok := m.clearedFields[category.FieldConfig] + return ok +} + +// ResetConfig resets all changes to the "config" field. +func (m *CategoryMutation) ResetConfig() { + m._config = nil + delete(m.clearedFields, category.FieldConfig) +} + +// SetDuration sets the "duration" field. +func (m *CategoryMutation) SetDuration(t time.Duration) { + m.duration = &t + m.addduration = nil +} + +// Duration returns the value of the "duration" field in the mutation. +func (m *CategoryMutation) Duration() (r time.Duration, exists bool) { + v := m.duration + if v == nil { + return + } + return *v, true +} + +// OldDuration returns the old "duration" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldDuration(ctx context.Context) (v time.Duration, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldDuration is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldDuration requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldDuration: %w", err) + } + return oldValue.Duration, nil +} + +// AddDuration adds t to the "duration" field. +func (m *CategoryMutation) AddDuration(t time.Duration) { + if m.addduration != nil { + *m.addduration += t + } else { + m.addduration = &t + } +} + +// AddedDuration returns the value that was added to the "duration" field in this mutation. +func (m *CategoryMutation) AddedDuration() (r time.Duration, exists bool) { + v := m.addduration + if v == nil { + return + } + return *v, true +} + +// ClearDuration clears the value of the "duration" field. +func (m *CategoryMutation) ClearDuration() { + m.duration = nil + m.addduration = nil + m.clearedFields[category.FieldDuration] = struct{}{} +} + +// DurationCleared returns if the "duration" field was cleared in this mutation. +func (m *CategoryMutation) DurationCleared() bool { + _, ok := m.clearedFields[category.FieldDuration] + return ok +} + +// ResetDuration resets all changes to the "duration" field. +func (m *CategoryMutation) ResetDuration() { + m.duration = nil + m.addduration = nil + delete(m.clearedFields, category.FieldDuration) +} + +// SetCount sets the "count" field. +func (m *CategoryMutation) SetCount(u uint64) { + m.count = &u + m.addcount = nil +} + +// Count returns the value of the "count" field in the mutation. +func (m *CategoryMutation) Count() (r uint64, exists bool) { + v := m.count + if v == nil { + return + } + return *v, true +} + +// OldCount returns the old "count" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldCount(ctx context.Context) (v uint64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCount is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCount requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCount: %w", err) + } + return oldValue.Count, nil +} + +// AddCount adds u to the "count" field. +func (m *CategoryMutation) AddCount(u int64) { + if m.addcount != nil { + *m.addcount += u + } else { + m.addcount = &u + } +} + +// AddedCount returns the value that was added to the "count" field in this mutation. +func (m *CategoryMutation) AddedCount() (r int64, exists bool) { + v := m.addcount + if v == nil { + return + } + return *v, true +} + +// ClearCount clears the value of the "count" field. +func (m *CategoryMutation) ClearCount() { + m.count = nil + m.addcount = nil + m.clearedFields[category.FieldCount] = struct{}{} +} + +// CountCleared returns if the "count" field was cleared in this mutation. +func (m *CategoryMutation) CountCleared() bool { + _, ok := m.clearedFields[category.FieldCount] + return ok +} + +// ResetCount resets all changes to the "count" field. +func (m *CategoryMutation) ResetCount() { + m.count = nil + m.addcount = nil + delete(m.clearedFields, category.FieldCount) +} + +// SetStrings sets the "strings" field. +func (m *CategoryMutation) SetStrings(s []string) { + m.strings = &s +} + +// Strings returns the value of the "strings" field in the mutation. +func (m *CategoryMutation) Strings() (r []string, exists bool) { + v := m.strings + if v == nil { + return + } + return *v, true +} + +// OldStrings returns the old "strings" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldStrings(ctx context.Context) (v []string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStrings is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStrings requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStrings: %w", err) + } + return oldValue.Strings, nil +} + +// ClearStrings clears the value of the "strings" field. +func (m *CategoryMutation) ClearStrings() { + m.strings = nil + m.clearedFields[category.FieldStrings] = struct{}{} +} + +// StringsCleared returns if the "strings" field was cleared in this mutation. +func (m *CategoryMutation) StringsCleared() bool { + _, ok := m.clearedFields[category.FieldStrings] + return ok +} + +// ResetStrings resets all changes to the "strings" field. +func (m *CategoryMutation) ResetStrings() { + m.strings = nil + delete(m.clearedFields, category.FieldStrings) +} + +// AddTodoIDs adds the "todos" edge to the Todo entity by ids. +func (m *CategoryMutation) AddTodoIDs(ids ...int) { + if m.todos == nil { + m.todos = make(map[int]struct{}) + } + for i := range ids { + m.todos[ids[i]] = struct{}{} + } +} + +// ClearTodos clears the "todos" edge to the Todo entity. +func (m *CategoryMutation) ClearTodos() { + m.clearedtodos = true +} + +// TodosCleared reports if the "todos" edge to the Todo entity was cleared. +func (m *CategoryMutation) TodosCleared() bool { + return m.clearedtodos +} + +// RemoveTodoIDs removes the "todos" edge to the Todo entity by IDs. +func (m *CategoryMutation) RemoveTodoIDs(ids ...int) { + if m.removedtodos == nil { + m.removedtodos = make(map[int]struct{}) + } + for i := range ids { + delete(m.todos, ids[i]) + m.removedtodos[ids[i]] = struct{}{} + } +} + +// RemovedTodos returns the removed IDs of the "todos" edge to the Todo entity. +func (m *CategoryMutation) RemovedTodosIDs() (ids []int) { + for id := range m.removedtodos { + ids = append(ids, id) + } + return +} + +// TodosIDs returns the "todos" edge IDs in the mutation. +func (m *CategoryMutation) TodosIDs() (ids []int) { + for id := range m.todos { + ids = append(ids, id) + } + return +} + +// ResetTodos resets all changes to the "todos" edge. +func (m *CategoryMutation) ResetTodos() { + m.todos = nil + m.clearedtodos = false + m.removedtodos = nil +} + +// Where appends a list predicates to the CategoryMutation builder. +func (m *CategoryMutation) Where(ps ...predicate.Category) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *CategoryMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (Category). +func (m *CategoryMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *CategoryMutation) Fields() []string { + fields := make([]string, 0, 6) + if m.text != nil { + fields = append(fields, category.FieldText) + } + if m.status != nil { + fields = append(fields, category.FieldStatus) + } + if m._config != nil { + fields = append(fields, category.FieldConfig) + } + if m.duration != nil { + fields = append(fields, category.FieldDuration) + } + if m.count != nil { + fields = append(fields, category.FieldCount) + } + if m.strings != nil { + fields = append(fields, category.FieldStrings) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *CategoryMutation) Field(name string) (ent.Value, bool) { + switch name { + case category.FieldText: + return m.Text() + case category.FieldStatus: + return m.Status() + case category.FieldConfig: + return m.Config() + case category.FieldDuration: + return m.Duration() + case category.FieldCount: + return m.Count() + case category.FieldStrings: + return m.Strings() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *CategoryMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case category.FieldText: + return m.OldText(ctx) + case category.FieldStatus: + return m.OldStatus(ctx) + case category.FieldConfig: + return m.OldConfig(ctx) + case category.FieldDuration: + return m.OldDuration(ctx) + case category.FieldCount: + return m.OldCount(ctx) + case category.FieldStrings: + return m.OldStrings(ctx) + } + return nil, fmt.Errorf("unknown Category field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *CategoryMutation) SetField(name string, value ent.Value) error { + switch name { + case category.FieldText: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetText(v) + return nil + case category.FieldStatus: + v, ok := value.(category.Status) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case category.FieldConfig: + v, ok := value.(*schematype.CategoryConfig) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetConfig(v) + return nil + case category.FieldDuration: + v, ok := value.(time.Duration) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetDuration(v) + return nil + case category.FieldCount: + v, ok := value.(uint64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCount(v) + return nil + case category.FieldStrings: + v, ok := value.([]string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStrings(v) + return nil + } + return fmt.Errorf("unknown Category field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *CategoryMutation) AddedFields() []string { + var fields []string + if m.addduration != nil { + fields = append(fields, category.FieldDuration) + } + if m.addcount != nil { + fields = append(fields, category.FieldCount) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *CategoryMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case category.FieldDuration: + return m.AddedDuration() + case category.FieldCount: + return m.AddedCount() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *CategoryMutation) AddField(name string, value ent.Value) error { + switch name { + case category.FieldDuration: + v, ok := value.(time.Duration) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddDuration(v) + return nil + case category.FieldCount: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddCount(v) + return nil + } + return fmt.Errorf("unknown Category numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *CategoryMutation) ClearedFields() []string { + var fields []string + if m.FieldCleared(category.FieldConfig) { + fields = append(fields, category.FieldConfig) + } + if m.FieldCleared(category.FieldDuration) { + fields = append(fields, category.FieldDuration) + } + if m.FieldCleared(category.FieldCount) { + fields = append(fields, category.FieldCount) + } + if m.FieldCleared(category.FieldStrings) { + fields = append(fields, category.FieldStrings) + } + return fields +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *CategoryMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *CategoryMutation) ClearField(name string) error { + switch name { + case category.FieldConfig: + m.ClearConfig() + return nil + case category.FieldDuration: + m.ClearDuration() + return nil + case category.FieldCount: + m.ClearCount() + return nil + case category.FieldStrings: + m.ClearStrings() + return nil + } + return fmt.Errorf("unknown Category nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *CategoryMutation) ResetField(name string) error { + switch name { + case category.FieldText: + m.ResetText() + return nil + case category.FieldStatus: + m.ResetStatus() + return nil + case category.FieldConfig: + m.ResetConfig() + return nil + case category.FieldDuration: + m.ResetDuration() + return nil + case category.FieldCount: + m.ResetCount() + return nil + case category.FieldStrings: + m.ResetStrings() + return nil + } + return fmt.Errorf("unknown Category field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *CategoryMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.todos != nil { + edges = append(edges, category.EdgeTodos) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *CategoryMutation) AddedIDs(name string) []ent.Value { + switch name { + case category.EdgeTodos: + ids := make([]ent.Value, 0, len(m.todos)) + for id := range m.todos { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *CategoryMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + if m.removedtodos != nil { + edges = append(edges, category.EdgeTodos) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *CategoryMutation) RemovedIDs(name string) []ent.Value { + switch name { + case category.EdgeTodos: + ids := make([]ent.Value, 0, len(m.removedtodos)) + for id := range m.removedtodos { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *CategoryMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedtodos { + edges = append(edges, category.EdgeTodos) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *CategoryMutation) EdgeCleared(name string) bool { + switch name { + case category.EdgeTodos: + return m.clearedtodos + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *CategoryMutation) ClearEdge(name string) error { + switch name { + } + return fmt.Errorf("unknown Category unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *CategoryMutation) ResetEdge(name string) error { + switch name { + case category.EdgeTodos: + m.ResetTodos() + return nil + } + return fmt.Errorf("unknown Category edge %s", name) +} + +// TodoMutation represents an operation that mutates the Todo nodes in the graph. +type TodoMutation struct { + config + op Op + typ string + id *int + created_at *time.Time + visibility_status *todo.VisibilityStatus + status *todo.Status + priority *int + addpriority *int + text *string + clearedFields map[string]struct{} + parent *int + clearedparent bool + children map[int]struct{} + removedchildren map[int]struct{} + clearedchildren bool + done bool + oldValue func(context.Context) (*Todo, error) + predicates []predicate.Todo +} + +var _ ent.Mutation = (*TodoMutation)(nil) + +// todoOption allows management of the mutation configuration using functional options. +type todoOption func(*TodoMutation) + +// newTodoMutation creates new mutation for the Todo entity. +func newTodoMutation(c config, op Op, opts ...todoOption) *TodoMutation { + m := &TodoMutation{ + config: c, + op: op, + typ: TypeTodo, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withTodoID sets the ID field of the mutation. +func withTodoID(id int) todoOption { + return func(m *TodoMutation) { + var ( + err error + once sync.Once + value *Todo + ) + m.oldValue = func(ctx context.Context) (*Todo, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().Todo.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withTodo sets the old Todo of the mutation. +func withTodo(node *Todo) todoOption { + return func(m *TodoMutation) { + m.oldValue = func(context.Context) (*Todo, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m TodoMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m TodoMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *TodoMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *TodoMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().Todo.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetCreatedAt sets the "created_at" field. +func (m *TodoMutation) SetCreatedAt(t time.Time) { + m.created_at = &t +} + +// CreatedAt returns the value of the "created_at" field in the mutation. +func (m *TodoMutation) CreatedAt() (r time.Time, exists bool) { + v := m.created_at + if v == nil { + return + } + return *v, true +} + +// OldCreatedAt returns the old "created_at" field's value of the Todo entity. +// If the Todo object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *TodoMutation) OldCreatedAt(ctx context.Context) (v time.Time, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldCreatedAt is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldCreatedAt requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldCreatedAt: %w", err) + } + return oldValue.CreatedAt, nil +} + +// ResetCreatedAt resets all changes to the "created_at" field. +func (m *TodoMutation) ResetCreatedAt() { + m.created_at = nil +} + +// SetVisibilityStatus sets the "visibility_status" field. +func (m *TodoMutation) SetVisibilityStatus(ts todo.VisibilityStatus) { + m.visibility_status = &ts +} + +// VisibilityStatus returns the value of the "visibility_status" field in the mutation. +func (m *TodoMutation) VisibilityStatus() (r todo.VisibilityStatus, exists bool) { + v := m.visibility_status + if v == nil { + return + } + return *v, true +} + +// OldVisibilityStatus returns the old "visibility_status" field's value of the Todo entity. +// If the Todo object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *TodoMutation) OldVisibilityStatus(ctx context.Context) (v todo.VisibilityStatus, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldVisibilityStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldVisibilityStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldVisibilityStatus: %w", err) + } + return oldValue.VisibilityStatus, nil +} + +// ResetVisibilityStatus resets all changes to the "visibility_status" field. +func (m *TodoMutation) ResetVisibilityStatus() { + m.visibility_status = nil +} + +// SetStatus sets the "status" field. +func (m *TodoMutation) SetStatus(t todo.Status) { + m.status = &t +} + +// Status returns the value of the "status" field in the mutation. +func (m *TodoMutation) Status() (r todo.Status, exists bool) { + v := m.status + if v == nil { + return + } + return *v, true +} + +// OldStatus returns the old "status" field's value of the Todo entity. +// If the Todo object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *TodoMutation) OldStatus(ctx context.Context) (v todo.Status, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldStatus is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldStatus requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldStatus: %w", err) + } + return oldValue.Status, nil +} + +// ResetStatus resets all changes to the "status" field. +func (m *TodoMutation) ResetStatus() { + m.status = nil +} + +// SetPriority sets the "priority" field. +func (m *TodoMutation) SetPriority(i int) { + m.priority = &i + m.addpriority = nil +} + +// Priority returns the value of the "priority" field in the mutation. +func (m *TodoMutation) Priority() (r int, exists bool) { + v := m.priority + if v == nil { + return + } + return *v, true +} + +// OldPriority returns the old "priority" field's value of the Todo entity. +// If the Todo object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *TodoMutation) OldPriority(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldPriority is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldPriority requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldPriority: %w", err) + } + return oldValue.Priority, nil +} + +// AddPriority adds i to the "priority" field. +func (m *TodoMutation) AddPriority(i int) { + if m.addpriority != nil { + *m.addpriority += i + } else { + m.addpriority = &i + } +} + +// AddedPriority returns the value that was added to the "priority" field in this mutation. +func (m *TodoMutation) AddedPriority() (r int, exists bool) { + v := m.addpriority + if v == nil { + return + } + return *v, true +} + +// ResetPriority resets all changes to the "priority" field. +func (m *TodoMutation) ResetPriority() { + m.priority = nil + m.addpriority = nil +} + +// SetText sets the "text" field. +func (m *TodoMutation) SetText(s string) { + m.text = &s +} + +// Text returns the value of the "text" field in the mutation. +func (m *TodoMutation) Text() (r string, exists bool) { + v := m.text + if v == nil { + return + } + return *v, true +} + +// OldText returns the old "text" field's value of the Todo entity. +// If the Todo object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *TodoMutation) OldText(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldText is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldText requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldText: %w", err) + } + return oldValue.Text, nil +} + +// ResetText resets all changes to the "text" field. +func (m *TodoMutation) ResetText() { + m.text = nil +} + +// SetParentID sets the "parent" edge to the Todo entity by id. +func (m *TodoMutation) SetParentID(id int) { + m.parent = &id +} + +// ClearParent clears the "parent" edge to the Todo entity. +func (m *TodoMutation) ClearParent() { + m.clearedparent = true +} + +// ParentCleared reports if the "parent" edge to the Todo entity was cleared. +func (m *TodoMutation) ParentCleared() bool { + return m.clearedparent +} + +// ParentID returns the "parent" edge ID in the mutation. +func (m *TodoMutation) ParentID() (id int, exists bool) { + if m.parent != nil { + return *m.parent, true + } + return +} + +// ParentIDs returns the "parent" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ParentID instead. It exists only for internal usage by the builders. +func (m *TodoMutation) ParentIDs() (ids []int) { + if id := m.parent; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetParent resets all changes to the "parent" edge. +func (m *TodoMutation) ResetParent() { + m.parent = nil + m.clearedparent = false +} + +// AddChildIDs adds the "children" edge to the Todo entity by ids. +func (m *TodoMutation) AddChildIDs(ids ...int) { + if m.children == nil { + m.children = make(map[int]struct{}) + } + for i := range ids { + m.children[ids[i]] = struct{}{} + } +} + +// ClearChildren clears the "children" edge to the Todo entity. +func (m *TodoMutation) ClearChildren() { + m.clearedchildren = true +} + +// ChildrenCleared reports if the "children" edge to the Todo entity was cleared. +func (m *TodoMutation) ChildrenCleared() bool { + return m.clearedchildren +} + +// RemoveChildIDs removes the "children" edge to the Todo entity by IDs. +func (m *TodoMutation) RemoveChildIDs(ids ...int) { + if m.removedchildren == nil { + m.removedchildren = make(map[int]struct{}) + } + for i := range ids { + delete(m.children, ids[i]) + m.removedchildren[ids[i]] = struct{}{} + } +} + +// RemovedChildren returns the removed IDs of the "children" edge to the Todo entity. +func (m *TodoMutation) RemovedChildrenIDs() (ids []int) { + for id := range m.removedchildren { + ids = append(ids, id) + } + return +} + +// ChildrenIDs returns the "children" edge IDs in the mutation. +func (m *TodoMutation) ChildrenIDs() (ids []int) { + for id := range m.children { + ids = append(ids, id) + } + return +} + +// ResetChildren resets all changes to the "children" edge. +func (m *TodoMutation) ResetChildren() { + m.children = nil + m.clearedchildren = false + m.removedchildren = nil +} + +// Where appends a list predicates to the TodoMutation builder. +func (m *TodoMutation) Where(ps ...predicate.Todo) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *TodoMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (Todo). +func (m *TodoMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *TodoMutation) Fields() []string { + fields := make([]string, 0, 5) + if m.created_at != nil { + fields = append(fields, todo.FieldCreatedAt) + } + if m.visibility_status != nil { + fields = append(fields, todo.FieldVisibilityStatus) + } + if m.status != nil { + fields = append(fields, todo.FieldStatus) + } + if m.priority != nil { + fields = append(fields, todo.FieldPriority) + } + if m.text != nil { + fields = append(fields, todo.FieldText) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *TodoMutation) Field(name string) (ent.Value, bool) { + switch name { + case todo.FieldCreatedAt: + return m.CreatedAt() + case todo.FieldVisibilityStatus: + return m.VisibilityStatus() + case todo.FieldStatus: + return m.Status() + case todo.FieldPriority: + return m.Priority() + case todo.FieldText: + return m.Text() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *TodoMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case todo.FieldCreatedAt: + return m.OldCreatedAt(ctx) + case todo.FieldVisibilityStatus: + return m.OldVisibilityStatus(ctx) + case todo.FieldStatus: + return m.OldStatus(ctx) + case todo.FieldPriority: + return m.OldPriority(ctx) + case todo.FieldText: + return m.OldText(ctx) + } + return nil, fmt.Errorf("unknown Todo field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *TodoMutation) SetField(name string, value ent.Value) error { + switch name { + case todo.FieldCreatedAt: + v, ok := value.(time.Time) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetCreatedAt(v) + return nil + case todo.FieldVisibilityStatus: + v, ok := value.(todo.VisibilityStatus) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetVisibilityStatus(v) + return nil + case todo.FieldStatus: + v, ok := value.(todo.Status) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetStatus(v) + return nil + case todo.FieldPriority: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetPriority(v) + return nil + case todo.FieldText: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetText(v) + return nil + } + return fmt.Errorf("unknown Todo field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *TodoMutation) AddedFields() []string { + var fields []string + if m.addpriority != nil { + fields = append(fields, todo.FieldPriority) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *TodoMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case todo.FieldPriority: + return m.AddedPriority() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *TodoMutation) AddField(name string, value ent.Value) error { + switch name { + case todo.FieldPriority: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddPriority(v) + return nil + } + return fmt.Errorf("unknown Todo numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *TodoMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *TodoMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *TodoMutation) ClearField(name string) error { + return fmt.Errorf("unknown Todo nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *TodoMutation) ResetField(name string) error { + switch name { + case todo.FieldCreatedAt: + m.ResetCreatedAt() + return nil + case todo.FieldVisibilityStatus: + m.ResetVisibilityStatus() + return nil + case todo.FieldStatus: + m.ResetStatus() + return nil + case todo.FieldPriority: + m.ResetPriority() + return nil + case todo.FieldText: + m.ResetText() + return nil + } + return fmt.Errorf("unknown Todo field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *TodoMutation) AddedEdges() []string { + edges := make([]string, 0, 2) + if m.parent != nil { + edges = append(edges, todo.EdgeParent) + } + if m.children != nil { + edges = append(edges, todo.EdgeChildren) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *TodoMutation) AddedIDs(name string) []ent.Value { + switch name { + case todo.EdgeParent: + if id := m.parent; id != nil { + return []ent.Value{*id} + } + case todo.EdgeChildren: + ids := make([]ent.Value, 0, len(m.children)) + for id := range m.children { + ids = append(ids, id) + } + return ids + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *TodoMutation) RemovedEdges() []string { + edges := make([]string, 0, 2) + if m.removedchildren != nil { + edges = append(edges, todo.EdgeChildren) + } + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *TodoMutation) RemovedIDs(name string) []ent.Value { + switch name { + case todo.EdgeChildren: + ids := make([]ent.Value, 0, len(m.removedchildren)) + for id := range m.removedchildren { + ids = append(ids, id) + } + return ids + } + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *TodoMutation) ClearedEdges() []string { + edges := make([]string, 0, 2) + if m.clearedparent { + edges = append(edges, todo.EdgeParent) + } + if m.clearedchildren { + edges = append(edges, todo.EdgeChildren) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *TodoMutation) EdgeCleared(name string) bool { + switch name { + case todo.EdgeParent: + return m.clearedparent + case todo.EdgeChildren: + return m.clearedchildren + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *TodoMutation) ClearEdge(name string) error { + switch name { + case todo.EdgeParent: + m.ClearParent() + return nil + } + return fmt.Errorf("unknown Todo unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *TodoMutation) ResetEdge(name string) error { + switch name { + case todo.EdgeParent: + m.ResetParent() + return nil + case todo.EdgeChildren: + m.ResetChildren() + return nil + } + return fmt.Errorf("unknown Todo edge %s", name) +} + +// UserMutation represents an operation that mutates the User nodes in the graph. +type UserMutation struct { + config + op Op + typ string + id *int + username *string + age *int + addage *int + amount *schema.Amount + addamount *schema.Amount + role *role.Role + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*User, error) + predicates []predicate.User +} + +var _ ent.Mutation = (*UserMutation)(nil) + +// userOption allows management of the mutation configuration using functional options. +type userOption func(*UserMutation) + +// newUserMutation creates new mutation for the User entity. +func newUserMutation(c config, op Op, opts ...userOption) *UserMutation { + m := &UserMutation{ + config: c, + op: op, + typ: TypeUser, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withUserID sets the ID field of the mutation. +func withUserID(id int) userOption { + return func(m *UserMutation) { + var ( + err error + once sync.Once + value *User + ) + m.oldValue = func(ctx context.Context) (*User, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().User.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withUser sets the old User of the mutation. +func withUser(node *User) userOption { + return func(m *UserMutation) { + m.oldValue = func(context.Context) (*User, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m UserMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m UserMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *UserMutation) ID() (id int, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *UserMutation) IDs(ctx context.Context) ([]int, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().User.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetUsername sets the "username" field. +func (m *UserMutation) SetUsername(s string) { + m.username = &s +} + +// Username returns the value of the "username" field in the mutation. +func (m *UserMutation) Username() (r string, exists bool) { + v := m.username + if v == nil { + return + } + return *v, true +} + +// OldUsername returns the old "username" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldUsername(ctx context.Context) (v string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUsername is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUsername requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUsername: %w", err) + } + return oldValue.Username, nil +} + +// ResetUsername resets all changes to the "username" field. +func (m *UserMutation) ResetUsername() { + m.username = nil +} + +// SetAge sets the "age" field. +func (m *UserMutation) SetAge(i int) { + m.age = &i + m.addage = nil +} + +// Age returns the value of the "age" field in the mutation. +func (m *UserMutation) Age() (r int, exists bool) { + v := m.age + if v == nil { + return + } + return *v, true +} + +// OldAge returns the old "age" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldAge(ctx context.Context) (v int, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldAge is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldAge requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldAge: %w", err) + } + return oldValue.Age, nil +} + +// AddAge adds i to the "age" field. +func (m *UserMutation) AddAge(i int) { + if m.addage != nil { + *m.addage += i + } else { + m.addage = &i + } +} + +// AddedAge returns the value that was added to the "age" field in this mutation. +func (m *UserMutation) AddedAge() (r int, exists bool) { + v := m.addage + if v == nil { + return + } + return *v, true +} + +// ResetAge resets all changes to the "age" field. +func (m *UserMutation) ResetAge() { + m.age = nil + m.addage = nil +} + +// SetAmount sets the "amount" field. +func (m *UserMutation) SetAmount(s schema.Amount) { + m.amount = &s + m.addamount = nil +} + +// Amount returns the value of the "amount" field in the mutation. +func (m *UserMutation) Amount() (r schema.Amount, exists bool) { + v := m.amount + if v == nil { + return + } + return *v, true +} + +// OldAmount returns the old "amount" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldAmount(ctx context.Context) (v schema.Amount, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldAmount is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldAmount requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldAmount: %w", err) + } + return oldValue.Amount, nil +} + +// AddAmount adds s to the "amount" field. +func (m *UserMutation) AddAmount(s schema.Amount) { + if m.addamount != nil { + *m.addamount += s + } else { + m.addamount = &s + } +} + +// AddedAmount returns the value that was added to the "amount" field in this mutation. +func (m *UserMutation) AddedAmount() (r schema.Amount, exists bool) { + v := m.addamount + if v == nil { + return + } + return *v, true +} + +// ResetAmount resets all changes to the "amount" field. +func (m *UserMutation) ResetAmount() { + m.amount = nil + m.addamount = nil +} + +// SetRole sets the "role" field. +func (m *UserMutation) SetRole(r role.Role) { + m.role = &r +} + +// Role returns the value of the "role" field in the mutation. +func (m *UserMutation) Role() (r role.Role, exists bool) { + v := m.role + if v == nil { + return + } + return *v, true +} + +// OldRole returns the old "role" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldRole(ctx context.Context) (v role.Role, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldRole is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldRole requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldRole: %w", err) + } + return oldValue.Role, nil +} + +// ResetRole resets all changes to the "role" field. +func (m *UserMutation) ResetRole() { + m.role = nil +} + +// Where appends a list predicates to the UserMutation builder. +func (m *UserMutation) Where(ps ...predicate.User) { + m.predicates = append(m.predicates, ps...) +} + +// Op returns the operation name. +func (m *UserMutation) Op() Op { + return m.op +} + +// Type returns the node type of this mutation (User). +func (m *UserMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *UserMutation) Fields() []string { + fields := make([]string, 0, 4) + if m.username != nil { + fields = append(fields, user.FieldUsername) + } + if m.age != nil { + fields = append(fields, user.FieldAge) + } + if m.amount != nil { + fields = append(fields, user.FieldAmount) + } + if m.role != nil { + fields = append(fields, user.FieldRole) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *UserMutation) Field(name string) (ent.Value, bool) { + switch name { + case user.FieldUsername: + return m.Username() + case user.FieldAge: + return m.Age() + case user.FieldAmount: + return m.Amount() + case user.FieldRole: + return m.Role() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case user.FieldUsername: + return m.OldUsername(ctx) + case user.FieldAge: + return m.OldAge(ctx) + case user.FieldAmount: + return m.OldAmount(ctx) + case user.FieldRole: + return m.OldRole(ctx) + } + return nil, fmt.Errorf("unknown User field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *UserMutation) SetField(name string, value ent.Value) error { + switch name { + case user.FieldUsername: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUsername(v) + return nil + case user.FieldAge: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetAge(v) + return nil + case user.FieldAmount: + v, ok := value.(schema.Amount) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetAmount(v) + return nil + case user.FieldRole: + v, ok := value.(role.Role) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetRole(v) + return nil + } + return fmt.Errorf("unknown User field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *UserMutation) AddedFields() []string { + var fields []string + if m.addage != nil { + fields = append(fields, user.FieldAge) + } + if m.addamount != nil { + fields = append(fields, user.FieldAmount) + } + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *UserMutation) AddedField(name string) (ent.Value, bool) { + switch name { + case user.FieldAge: + return m.AddedAge() + case user.FieldAmount: + return m.AddedAmount() + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *UserMutation) AddField(name string, value ent.Value) error { + switch name { + case user.FieldAge: + v, ok := value.(int) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddAge(v) + return nil + case user.FieldAmount: + v, ok := value.(schema.Amount) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.AddAmount(v) + return nil + } + return fmt.Errorf("unknown User numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *UserMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *UserMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *UserMutation) ClearField(name string) error { + return fmt.Errorf("unknown User nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *UserMutation) ResetField(name string) error { + switch name { + case user.FieldUsername: + m.ResetUsername() + return nil + case user.FieldAge: + m.ResetAge() + return nil + case user.FieldAmount: + m.ResetAmount() + return nil + case user.FieldRole: + m.ResetRole() + return nil + } + return fmt.Errorf("unknown User field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *UserMutation) AddedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *UserMutation) AddedIDs(name string) []ent.Value { + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *UserMutation) RemovedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *UserMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *UserMutation) ClearedEdges() []string { + edges := make([]string, 0, 0) + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *UserMutation) EdgeCleared(name string) bool { + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *UserMutation) ClearEdge(name string) error { + return fmt.Errorf("unknown User unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *UserMutation) ResetEdge(name string) error { + return fmt.Errorf("unknown User edge %s", name) +} diff --git a/entgql/internal/todoplugin/ent/pagination_test.go b/entgql/internal/todoplugin/ent/pagination_test.go new file mode 100644 index 000000000..86aefb3b6 --- /dev/null +++ b/entgql/internal/todoplugin/ent/pagination_test.go @@ -0,0 +1,73 @@ +// Copyright 2004-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by entc, DO NOT EDIT. + +package ent_test + +import ( + "bytes" + "strconv" + "testing" + + "entgo.io/contrib/entgql/internal/todo/ent" + "github.com/stretchr/testify/assert" +) + +func TestCursorEncoding(t *testing.T) { + t.Run("EncodeDecode", func(t *testing.T) { + const ( + id = 42 + value = "foobar" + quote = uint8('"') + ) + var buf bytes.Buffer + c := ent.Cursor{ID: id, Value: value} + c.MarshalGQL(&buf) + s := buf.String() + assert.Equal(t, quote, s[0]) + n := len(s) - 1 + assert.Equal(t, quote, s[n]) + c = ent.Cursor{} + err := c.UnmarshalGQL(s[1:n]) + assert.NoError(t, err) + assert.Equal(t, id, c.ID) + assert.Equal(t, value, c.Value) + }) + t.Run("EncodeNoValue", func(t *testing.T) { + const id = 55 + var buf bytes.Buffer + c := ent.Cursor{ID: id} + c.MarshalGQL(&buf) + s, err := strconv.Unquote(buf.String()) + assert.NoError(t, err) + c = ent.Cursor{} + err = c.UnmarshalGQL(s) + assert.NoError(t, err) + assert.Equal(t, id, c.ID) + assert.Nil(t, c.Value) + }) + t.Run("DecodeBadInput", func(t *testing.T) { + inputs := []interface{}{ + 0xbadbeef, + "cursor@bad123", + "Y3Vyc29yQGJhZDEyMw==", + } + for _, input := range inputs { + var c ent.Cursor + err := c.UnmarshalGQL(input) + assert.Error(t, err) + } + }) +} diff --git a/entgql/internal/todoplugin/ent/predicate/predicate.go b/entgql/internal/todoplugin/ent/predicate/predicate.go new file mode 100644 index 000000000..e5dac9a0c --- /dev/null +++ b/entgql/internal/todoplugin/ent/predicate/predicate.go @@ -0,0 +1,30 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package predicate + +import ( + "entgo.io/ent/dialect/sql" +) + +// Category is the predicate function for category builders. +type Category func(*sql.Selector) + +// Todo is the predicate function for todo builders. +type Todo func(*sql.Selector) + +// User is the predicate function for user builders. +type User func(*sql.Selector) diff --git a/entgql/internal/todoplugin/ent/role/role.go b/entgql/internal/todoplugin/ent/role/role.go new file mode 100644 index 000000000..90620a357 --- /dev/null +++ b/entgql/internal/todoplugin/ent/role/role.go @@ -0,0 +1,40 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package role + +import "io" + +type Role string + +const ( + Admin Role = "ADMIN" + User Role = "USER" + Unknown Role = "UNKNOWN" +) + +func (Role) Values() (roles []string) { + for _, r := range []Role{Admin, User, Unknown} { + roles = append(roles, string(r)) + } + return +} + +func (r Role) MarshalGQL(w io.Writer) { + panic("implement me") +} + +func (r Role) UnmarshalGQL(v interface{}) error { + panic("implement me") +} diff --git a/entgql/internal/todoplugin/ent/runtime.go b/entgql/internal/todoplugin/ent/runtime.go new file mode 100644 index 000000000..b11a54f04 --- /dev/null +++ b/entgql/internal/todoplugin/ent/runtime.go @@ -0,0 +1,51 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" +) + +// The init function reads all schema descriptors with runtime code +// (default values, validators, hooks and policies) and stitches it +// to their package variables. +func init() { + categoryFields := schema.Category{}.Fields() + _ = categoryFields + // categoryDescText is the schema descriptor for text field. + categoryDescText := categoryFields[0].Descriptor() + // category.TextValidator is a validator for the "text" field. It is called by the builders before save. + category.TextValidator = categoryDescText.Validators[0].(func(string) error) + todoFields := schema.Todo{}.Fields() + _ = todoFields + // todoDescCreatedAt is the schema descriptor for created_at field. + todoDescCreatedAt := todoFields[0].Descriptor() + // todo.DefaultCreatedAt holds the default value on creation for the created_at field. + todo.DefaultCreatedAt = todoDescCreatedAt.Default.(func() time.Time) + // todoDescPriority is the schema descriptor for priority field. + todoDescPriority := todoFields[3].Descriptor() + // todo.DefaultPriority holds the default value on creation for the priority field. + todo.DefaultPriority = todoDescPriority.Default.(int) + // todoDescText is the schema descriptor for text field. + todoDescText := todoFields[4].Descriptor() + // todo.TextValidator is a validator for the "text" field. It is called by the builders before save. + todo.TextValidator = todoDescText.Validators[0].(func(string) error) +} diff --git a/entgql/internal/todoplugin/ent/runtime/runtime.go b/entgql/internal/todoplugin/ent/runtime/runtime.go new file mode 100644 index 000000000..3e5b58b0e --- /dev/null +++ b/entgql/internal/todoplugin/ent/runtime/runtime.go @@ -0,0 +1,24 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package runtime + +// The schema-stitching logic is generated in entgo.io/contrib/entgql/internal/todoplugin/ent/runtime.go + +const ( + Version = "v0.9.2-0.20211220092907-4d01a56b8de7" // Version of ent codegen. + Sum = "h1:v5R9L5IE4fakNcs5OlNKFZ5Cn0Oa6ogs2o8qmHSWO4Y=" // Sum of ent codegen. +) diff --git a/entgql/internal/todoplugin/ent/schema/category.go b/entgql/internal/todoplugin/ent/schema/category.go new file mode 100644 index 000000000..3dc918bf1 --- /dev/null +++ b/entgql/internal/todoplugin/ent/schema/category.go @@ -0,0 +1,87 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package schema + +import ( + "time" + + "entgo.io/contrib/entgql" + "entgo.io/ent" + "entgo.io/ent/dialect" + "entgo.io/ent/schema" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" +) + +// Category holds the schema definition for the Category entity. +type Category struct { + ent.Schema +} + +// Fields of the Category. +func (Category) Fields() []ent.Field { + return []ent.Field{ + field.Text("text"). + NotEmpty(). + Annotations( + entgql.OrderField("TEXT"), + ), + field.Enum("status"). + NamedValues( + "Enabled", "ENABLED", + "Disabled", "DISABLED", + ). + Annotations( + entgql.Type("CategoryStatus"), + ), + field.Other("config", &schematype.CategoryConfig{}). + SchemaType(map[string]string{ + dialect.SQLite: "json", + }). + Optional(). + Annotations( + entgql.Type("CategoryConfig"), + ), + field.Int64("duration"). + GoType(time.Duration(0)). + Optional(). + Annotations( + entgql.OrderField("DURATION"), + entgql.Type("Duration"), + ), + field.Uint64("count"). + Optional(). + Annotations( + entgql.Type("Uint64"), + ), + field.Strings("strings"). + Optional(), + } +} + +// Edges of the Category. +func (Category) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("todos", Todo.Type). + Annotations(entgql.Unbind()), + } +} + +// Annotations returns todo annotations. +func (Category) Annotations() []schema.Annotation { + return []schema.Annotation{} +} diff --git a/entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go b/entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go new file mode 100644 index 000000000..1c150a0b5 --- /dev/null +++ b/entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go @@ -0,0 +1,48 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package durationgql + +import ( + "encoding/json" + "fmt" + "io" + "strconv" + "time" + + "github.com/99designs/gqlgen/graphql" +) + +func MarshalDuration(t time.Duration) graphql.Marshaler { + return graphql.WriterFunc(func(w io.Writer) { + _, _ = io.WriteString(w, strconv.FormatInt(int64(t), 10)) + }) +} + +func UnmarshalDuration(v interface{}) (time.Duration, error) { + switch v := v.(type) { + case int64: + return time.Duration(v), nil + case string: + return time.ParseDuration(v) + case json.Number: + i, err := v.Int64() + if err != nil { + return 0, err + } + return time.Duration(i), nil + default: + return 0, fmt.Errorf("invalid type %T, expect string", v) + } +} diff --git a/entgql/internal/todoplugin/ent/schema/schematype/schematype.go b/entgql/internal/todoplugin/ent/schema/schematype/schematype.go new file mode 100644 index 000000000..413fc5d03 --- /dev/null +++ b/entgql/internal/todoplugin/ent/schema/schematype/schematype.go @@ -0,0 +1,40 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package schematype provides custom types for ent/schema. +package schematype + +import ( + "database/sql/driver" + "encoding/json" +) + +// CategoryConfig implements the field.ValueScanner interface. +type CategoryConfig struct { + MaxMembers int `json:"maxMembers,omitempty"` +} + +func (t *CategoryConfig) Scan(v interface{}) (err error) { + switch v := v.(type) { + case string: + err = json.Unmarshal([]byte(v), t) + case []byte: + err = json.Unmarshal(v, t) + } + return +} + +func (t *CategoryConfig) Value() (driver.Value, error) { + return json.Marshal(t) +} diff --git a/entgql/internal/todoplugin/ent/schema/todo.go b/entgql/internal/todoplugin/ent/schema/todo.go new file mode 100644 index 000000000..51120f13a --- /dev/null +++ b/entgql/internal/todoplugin/ent/schema/todo.go @@ -0,0 +1,84 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package schema + +import ( + "time" + + "entgo.io/ent/schema" + + "entgo.io/contrib/entgql" + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +// Todo defines the todo type schema. +type Todo struct { + ent.Schema +} + +// Fields returns todo fields. +func (Todo) Fields() []ent.Field { + return []ent.Field{ + field.Time("created_at"). + Default(time.Now). + Immutable(). + Annotations( + entgql.OrderField("CREATED_AT"), + ), + field.Enum("visibility_status"). + NamedValues( + "Listing", "LISTING", + "Hidden", "HIDDEN", + ). + Default("HIDDEN"). + Annotations( + entgql.OrderField("VISIBILITY_STATUS"), + ), + field.Enum("status"). + NamedValues( + "InProgress", "IN_PROGRESS", + "Completed", "COMPLETED", + ). + Annotations( + entgql.OrderField("STATUS"), + ), + field.Int("priority"). + Default(0). + Annotations( + entgql.OrderField("PRIORITY"), + ), + field.Text("text"). + NotEmpty(). + Annotations( + entgql.OrderField("TEXT"), + ), + } +} + +// Edges returns todo edges. +func (Todo) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("children", Todo.Type). + From("parent"). + Unique(), + } +} + +// Annotations returns todo annotations. +func (Todo) Annotations() []schema.Annotation { + return []schema.Annotation{} +} diff --git a/entgql/internal/todoplugin/ent/schema/user.go b/entgql/internal/todoplugin/ent/schema/user.go new file mode 100644 index 000000000..f90493e21 --- /dev/null +++ b/entgql/internal/todoplugin/ent/schema/user.go @@ -0,0 +1,47 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package schema + +import ( + "entgo.io/contrib/entgql" + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/ent" + "entgo.io/ent/schema/field" +) + +type Amount float64 + +// User defines the User type schema. +type User struct { + ent.Schema +} + +// Fields returns User fields. +func (User) Fields() []ent.Field { + return []ent.Field{ + field.String("username"), + field.Int("age"). + Annotations(entgql.Annotation{ + Type: "Float", + }), + field.Float("amount"). + GoType(Amount(0)). + Annotations(entgql.Annotation{ + Type: "Float", + }), + field.Enum("role"). + GoType(role.Unknown), + } +} diff --git a/entgql/internal/todoplugin/ent/todo.go b/entgql/internal/todoplugin/ent/todo.go new file mode 100644 index 000000000..1b7f59c7f --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo.go @@ -0,0 +1,223 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql" +) + +// Todo is the model entity for the Todo schema. +type Todo struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // CreatedAt holds the value of the "created_at" field. + CreatedAt time.Time `json:"created_at,omitempty"` + // VisibilityStatus holds the value of the "visibility_status" field. + VisibilityStatus todo.VisibilityStatus `json:"visibility_status,omitempty"` + // Status holds the value of the "status" field. + Status todo.Status `json:"status,omitempty"` + // Priority holds the value of the "priority" field. + Priority int `json:"priority,omitempty"` + // Text holds the value of the "text" field. + Text string `json:"text,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the TodoQuery when eager-loading is set. + Edges TodoEdges `json:"edges"` + category_todos *int + todo_children *int +} + +// TodoEdges holds the relations/edges for other nodes in the graph. +type TodoEdges struct { + // Parent holds the value of the parent edge. + Parent *Todo `json:"parent,omitempty"` + // Children holds the value of the children edge. + Children []*Todo `json:"children,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [2]bool +} + +// ParentOrErr returns the Parent value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e TodoEdges) ParentOrErr() (*Todo, error) { + if e.loadedTypes[0] { + if e.Parent == nil { + // The edge parent was loaded in eager-loading, + // but was not found. + return nil, &NotFoundError{label: todo.Label} + } + return e.Parent, nil + } + return nil, &NotLoadedError{edge: "parent"} +} + +// ChildrenOrErr returns the Children value or an error if the edge +// was not loaded in eager-loading. +func (e TodoEdges) ChildrenOrErr() ([]*Todo, error) { + if e.loadedTypes[1] { + return e.Children, nil + } + return nil, &NotLoadedError{edge: "children"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*Todo) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case todo.FieldID, todo.FieldPriority: + values[i] = new(sql.NullInt64) + case todo.FieldVisibilityStatus, todo.FieldStatus, todo.FieldText: + values[i] = new(sql.NullString) + case todo.FieldCreatedAt: + values[i] = new(sql.NullTime) + case todo.ForeignKeys[0]: // category_todos + values[i] = new(sql.NullInt64) + case todo.ForeignKeys[1]: // todo_children + values[i] = new(sql.NullInt64) + default: + return nil, fmt.Errorf("unexpected column %q for type Todo", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the Todo fields. +func (t *Todo) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case todo.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + t.ID = int(value.Int64) + case todo.FieldCreatedAt: + if value, ok := values[i].(*sql.NullTime); !ok { + return fmt.Errorf("unexpected type %T for field created_at", values[i]) + } else if value.Valid { + t.CreatedAt = value.Time + } + case todo.FieldVisibilityStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field visibility_status", values[i]) + } else if value.Valid { + t.VisibilityStatus = todo.VisibilityStatus(value.String) + } + case todo.FieldStatus: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field status", values[i]) + } else if value.Valid { + t.Status = todo.Status(value.String) + } + case todo.FieldPriority: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field priority", values[i]) + } else if value.Valid { + t.Priority = int(value.Int64) + } + case todo.FieldText: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field text", values[i]) + } else if value.Valid { + t.Text = value.String + } + case todo.ForeignKeys[0]: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field category_todos", value) + } else if value.Valid { + t.category_todos = new(int) + *t.category_todos = int(value.Int64) + } + case todo.ForeignKeys[1]: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for edge-field todo_children", value) + } else if value.Valid { + t.todo_children = new(int) + *t.todo_children = int(value.Int64) + } + } + } + return nil +} + +// QueryParent queries the "parent" edge of the Todo entity. +func (t *Todo) QueryParent() *TodoQuery { + return (&TodoClient{config: t.config}).QueryParent(t) +} + +// QueryChildren queries the "children" edge of the Todo entity. +func (t *Todo) QueryChildren() *TodoQuery { + return (&TodoClient{config: t.config}).QueryChildren(t) +} + +// Update returns a builder for updating this Todo. +// Note that you need to call Todo.Unwrap() before calling this method if this Todo +// was returned from a transaction, and the transaction was committed or rolled back. +func (t *Todo) Update() *TodoUpdateOne { + return (&TodoClient{config: t.config}).UpdateOne(t) +} + +// Unwrap unwraps the Todo entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (t *Todo) Unwrap() *Todo { + tx, ok := t.config.driver.(*txDriver) + if !ok { + panic("ent: Todo is not a transactional entity") + } + t.config.driver = tx.drv + return t +} + +// String implements the fmt.Stringer. +func (t *Todo) String() string { + var builder strings.Builder + builder.WriteString("Todo(") + builder.WriteString(fmt.Sprintf("id=%v", t.ID)) + builder.WriteString(", created_at=") + builder.WriteString(t.CreatedAt.Format(time.ANSIC)) + builder.WriteString(", visibility_status=") + builder.WriteString(fmt.Sprintf("%v", t.VisibilityStatus)) + builder.WriteString(", status=") + builder.WriteString(fmt.Sprintf("%v", t.Status)) + builder.WriteString(", priority=") + builder.WriteString(fmt.Sprintf("%v", t.Priority)) + builder.WriteString(", text=") + builder.WriteString(t.Text) + builder.WriteByte(')') + return builder.String() +} + +// Todos is a parsable slice of Todo. +type Todos []*Todo + +func (t Todos) config(cfg config) { + for _i := range t { + t[_i].config = cfg + } +} diff --git a/entgql/internal/todoplugin/ent/todo/todo.go b/entgql/internal/todoplugin/ent/todo/todo.go new file mode 100644 index 000000000..fcfae4946 --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo/todo.go @@ -0,0 +1,181 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package todo + +import ( + "fmt" + "io" + "strconv" + "time" +) + +const ( + // Label holds the string label denoting the todo type in the database. + Label = "todo" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldCreatedAt holds the string denoting the created_at field in the database. + FieldCreatedAt = "created_at" + // FieldVisibilityStatus holds the string denoting the visibility_status field in the database. + FieldVisibilityStatus = "visibility_status" + // FieldStatus holds the string denoting the status field in the database. + FieldStatus = "status" + // FieldPriority holds the string denoting the priority field in the database. + FieldPriority = "priority" + // FieldText holds the string denoting the text field in the database. + FieldText = "text" + // EdgeParent holds the string denoting the parent edge name in mutations. + EdgeParent = "parent" + // EdgeChildren holds the string denoting the children edge name in mutations. + EdgeChildren = "children" + // Table holds the table name of the todo in the database. + Table = "todos" + // ParentTable is the table that holds the parent relation/edge. + ParentTable = "todos" + // ParentColumn is the table column denoting the parent relation/edge. + ParentColumn = "todo_children" + // ChildrenTable is the table that holds the children relation/edge. + ChildrenTable = "todos" + // ChildrenColumn is the table column denoting the children relation/edge. + ChildrenColumn = "todo_children" +) + +// Columns holds all SQL columns for todo fields. +var Columns = []string{ + FieldID, + FieldCreatedAt, + FieldVisibilityStatus, + FieldStatus, + FieldPriority, + FieldText, +} + +// ForeignKeys holds the SQL foreign-keys that are owned by the "todos" +// table and are not defined as standalone fields in the schema. +var ForeignKeys = []string{ + "category_todos", + "todo_children", +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + for i := range ForeignKeys { + if column == ForeignKeys[i] { + return true + } + } + return false +} + +var ( + // DefaultCreatedAt holds the default value on creation for the "created_at" field. + DefaultCreatedAt func() time.Time + // DefaultPriority holds the default value on creation for the "priority" field. + DefaultPriority int + // TextValidator is a validator for the "text" field. It is called by the builders before save. + TextValidator func(string) error +) + +// VisibilityStatus defines the type for the "visibility_status" enum field. +type VisibilityStatus string + +// VisibilityStatusHidden is the default value of the VisibilityStatus enum. +const DefaultVisibilityStatus = VisibilityStatusHidden + +// VisibilityStatus values. +const ( + VisibilityStatusListing VisibilityStatus = "LISTING" + VisibilityStatusHidden VisibilityStatus = "HIDDEN" +) + +func (vs VisibilityStatus) String() string { + return string(vs) +} + +// VisibilityStatusValidator is a validator for the "visibility_status" field enum values. It is called by the builders before save. +func VisibilityStatusValidator(vs VisibilityStatus) error { + switch vs { + case VisibilityStatusListing, VisibilityStatusHidden: + return nil + default: + return fmt.Errorf("todo: invalid enum value for visibility_status field: %q", vs) + } +} + +// Status defines the type for the "status" enum field. +type Status string + +// Status values. +const ( + StatusInProgress Status = "IN_PROGRESS" + StatusCompleted Status = "COMPLETED" +) + +func (s Status) String() string { + return string(s) +} + +// StatusValidator is a validator for the "status" field enum values. It is called by the builders before save. +func StatusValidator(s Status) error { + switch s { + case StatusInProgress, StatusCompleted: + return nil + default: + return fmt.Errorf("todo: invalid enum value for status field: %q", s) + } +} + +// MarshalGQL implements graphql.Marshaler interface. +func (e VisibilityStatus) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(e.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (e *VisibilityStatus) UnmarshalGQL(val interface{}) error { + str, ok := val.(string) + if !ok { + return fmt.Errorf("enum %T must be a string", val) + } + *e = VisibilityStatus(str) + if err := VisibilityStatusValidator(*e); err != nil { + return fmt.Errorf("%s is not a valid VisibilityStatus", str) + } + return nil +} + +// MarshalGQL implements graphql.Marshaler interface. +func (e Status) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(e.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (e *Status) UnmarshalGQL(val interface{}) error { + str, ok := val.(string) + if !ok { + return fmt.Errorf("enum %T must be a string", val) + } + *e = Status(str) + if err := StatusValidator(*e); err != nil { + return fmt.Errorf("%s is not a valid Status", str) + } + return nil +} diff --git a/entgql/internal/todoplugin/ent/todo/where.go b/entgql/internal/todoplugin/ent/todo/where.go new file mode 100644 index 000000000..d4a758465 --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo/where.go @@ -0,0 +1,576 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package todo + +import ( + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ. +func CreatedAt(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCreatedAt), v)) + }) +} + +// Priority applies equality check predicate on the "priority" field. It's identical to PriorityEQ. +func Priority(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldPriority), v)) + }) +} + +// Text applies equality check predicate on the "text" field. It's identical to TextEQ. +func Text(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldText), v)) + }) +} + +// CreatedAtEQ applies the EQ predicate on the "created_at" field. +func CreatedAtEQ(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtNEQ applies the NEQ predicate on the "created_at" field. +func CreatedAtNEQ(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtIn applies the In predicate on the "created_at" field. +func CreatedAtIn(vs ...time.Time) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldCreatedAt), v...)) + }) +} + +// CreatedAtNotIn applies the NotIn predicate on the "created_at" field. +func CreatedAtNotIn(vs ...time.Time) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldCreatedAt), v...)) + }) +} + +// CreatedAtGT applies the GT predicate on the "created_at" field. +func CreatedAtGT(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtGTE applies the GTE predicate on the "created_at" field. +func CreatedAtGTE(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtLT applies the LT predicate on the "created_at" field. +func CreatedAtLT(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldCreatedAt), v)) + }) +} + +// CreatedAtLTE applies the LTE predicate on the "created_at" field. +func CreatedAtLTE(v time.Time) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldCreatedAt), v)) + }) +} + +// VisibilityStatusEQ applies the EQ predicate on the "visibility_status" field. +func VisibilityStatusEQ(v VisibilityStatus) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldVisibilityStatus), v)) + }) +} + +// VisibilityStatusNEQ applies the NEQ predicate on the "visibility_status" field. +func VisibilityStatusNEQ(v VisibilityStatus) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldVisibilityStatus), v)) + }) +} + +// VisibilityStatusIn applies the In predicate on the "visibility_status" field. +func VisibilityStatusIn(vs ...VisibilityStatus) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldVisibilityStatus), v...)) + }) +} + +// VisibilityStatusNotIn applies the NotIn predicate on the "visibility_status" field. +func VisibilityStatusNotIn(vs ...VisibilityStatus) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldVisibilityStatus), v...)) + }) +} + +// StatusEQ applies the EQ predicate on the "status" field. +func StatusEQ(v Status) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldStatus), v)) + }) +} + +// StatusNEQ applies the NEQ predicate on the "status" field. +func StatusNEQ(v Status) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldStatus), v)) + }) +} + +// StatusIn applies the In predicate on the "status" field. +func StatusIn(vs ...Status) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldStatus), v...)) + }) +} + +// StatusNotIn applies the NotIn predicate on the "status" field. +func StatusNotIn(vs ...Status) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldStatus), v...)) + }) +} + +// PriorityEQ applies the EQ predicate on the "priority" field. +func PriorityEQ(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldPriority), v)) + }) +} + +// PriorityNEQ applies the NEQ predicate on the "priority" field. +func PriorityNEQ(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldPriority), v)) + }) +} + +// PriorityIn applies the In predicate on the "priority" field. +func PriorityIn(vs ...int) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldPriority), v...)) + }) +} + +// PriorityNotIn applies the NotIn predicate on the "priority" field. +func PriorityNotIn(vs ...int) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldPriority), v...)) + }) +} + +// PriorityGT applies the GT predicate on the "priority" field. +func PriorityGT(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldPriority), v)) + }) +} + +// PriorityGTE applies the GTE predicate on the "priority" field. +func PriorityGTE(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldPriority), v)) + }) +} + +// PriorityLT applies the LT predicate on the "priority" field. +func PriorityLT(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldPriority), v)) + }) +} + +// PriorityLTE applies the LTE predicate on the "priority" field. +func PriorityLTE(v int) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldPriority), v)) + }) +} + +// TextEQ applies the EQ predicate on the "text" field. +func TextEQ(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldText), v)) + }) +} + +// TextNEQ applies the NEQ predicate on the "text" field. +func TextNEQ(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldText), v)) + }) +} + +// TextIn applies the In predicate on the "text" field. +func TextIn(vs ...string) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldText), v...)) + }) +} + +// TextNotIn applies the NotIn predicate on the "text" field. +func TextNotIn(vs ...string) predicate.Todo { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Todo(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldText), v...)) + }) +} + +// TextGT applies the GT predicate on the "text" field. +func TextGT(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldText), v)) + }) +} + +// TextGTE applies the GTE predicate on the "text" field. +func TextGTE(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldText), v)) + }) +} + +// TextLT applies the LT predicate on the "text" field. +func TextLT(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldText), v)) + }) +} + +// TextLTE applies the LTE predicate on the "text" field. +func TextLTE(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldText), v)) + }) +} + +// TextContains applies the Contains predicate on the "text" field. +func TextContains(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldText), v)) + }) +} + +// TextHasPrefix applies the HasPrefix predicate on the "text" field. +func TextHasPrefix(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldText), v)) + }) +} + +// TextHasSuffix applies the HasSuffix predicate on the "text" field. +func TextHasSuffix(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldText), v)) + }) +} + +// TextEqualFold applies the EqualFold predicate on the "text" field. +func TextEqualFold(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldText), v)) + }) +} + +// TextContainsFold applies the ContainsFold predicate on the "text" field. +func TextContainsFold(v string) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldText), v)) + }) +} + +// HasParent applies the HasEdge predicate on the "parent" edge. +func HasParent() predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ParentTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasParentWith applies the HasEdge predicate on the "parent" edge with a given conditions (other predicates). +func HasParentWith(preds ...predicate.Todo) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasChildren applies the HasEdge predicate on the "children" edge. +func HasChildren() predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ChildrenTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasChildrenWith applies the HasEdge predicate on the "children" edge with a given conditions (other predicates). +func HasChildrenWith(preds ...predicate.Todo) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.Todo) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.Todo) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.Todo) predicate.Todo { + return predicate.Todo(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/entgql/internal/todoplugin/ent/todo_create.go b/entgql/internal/todoplugin/ent/todo_create.go new file mode 100644 index 000000000..088d9fe41 --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo_create.go @@ -0,0 +1,433 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// TodoCreate is the builder for creating a Todo entity. +type TodoCreate struct { + config + mutation *TodoMutation + hooks []Hook +} + +// SetCreatedAt sets the "created_at" field. +func (tc *TodoCreate) SetCreatedAt(t time.Time) *TodoCreate { + tc.mutation.SetCreatedAt(t) + return tc +} + +// SetNillableCreatedAt sets the "created_at" field if the given value is not nil. +func (tc *TodoCreate) SetNillableCreatedAt(t *time.Time) *TodoCreate { + if t != nil { + tc.SetCreatedAt(*t) + } + return tc +} + +// SetVisibilityStatus sets the "visibility_status" field. +func (tc *TodoCreate) SetVisibilityStatus(ts todo.VisibilityStatus) *TodoCreate { + tc.mutation.SetVisibilityStatus(ts) + return tc +} + +// SetNillableVisibilityStatus sets the "visibility_status" field if the given value is not nil. +func (tc *TodoCreate) SetNillableVisibilityStatus(ts *todo.VisibilityStatus) *TodoCreate { + if ts != nil { + tc.SetVisibilityStatus(*ts) + } + return tc +} + +// SetStatus sets the "status" field. +func (tc *TodoCreate) SetStatus(t todo.Status) *TodoCreate { + tc.mutation.SetStatus(t) + return tc +} + +// SetPriority sets the "priority" field. +func (tc *TodoCreate) SetPriority(i int) *TodoCreate { + tc.mutation.SetPriority(i) + return tc +} + +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (tc *TodoCreate) SetNillablePriority(i *int) *TodoCreate { + if i != nil { + tc.SetPriority(*i) + } + return tc +} + +// SetText sets the "text" field. +func (tc *TodoCreate) SetText(s string) *TodoCreate { + tc.mutation.SetText(s) + return tc +} + +// SetParentID sets the "parent" edge to the Todo entity by ID. +func (tc *TodoCreate) SetParentID(id int) *TodoCreate { + tc.mutation.SetParentID(id) + return tc +} + +// SetNillableParentID sets the "parent" edge to the Todo entity by ID if the given value is not nil. +func (tc *TodoCreate) SetNillableParentID(id *int) *TodoCreate { + if id != nil { + tc = tc.SetParentID(*id) + } + return tc +} + +// SetParent sets the "parent" edge to the Todo entity. +func (tc *TodoCreate) SetParent(t *Todo) *TodoCreate { + return tc.SetParentID(t.ID) +} + +// AddChildIDs adds the "children" edge to the Todo entity by IDs. +func (tc *TodoCreate) AddChildIDs(ids ...int) *TodoCreate { + tc.mutation.AddChildIDs(ids...) + return tc +} + +// AddChildren adds the "children" edges to the Todo entity. +func (tc *TodoCreate) AddChildren(t ...*Todo) *TodoCreate { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return tc.AddChildIDs(ids...) +} + +// Mutation returns the TodoMutation object of the builder. +func (tc *TodoCreate) Mutation() *TodoMutation { + return tc.mutation +} + +// Save creates the Todo in the database. +func (tc *TodoCreate) Save(ctx context.Context) (*Todo, error) { + var ( + err error + node *Todo + ) + tc.defaults() + if len(tc.hooks) == 0 { + if err = tc.check(); err != nil { + return nil, err + } + node, err = tc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*TodoMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = tc.check(); err != nil { + return nil, err + } + tc.mutation = mutation + if node, err = tc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(tc.hooks) - 1; i >= 0; i-- { + if tc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = tc.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, tc.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (tc *TodoCreate) SaveX(ctx context.Context) *Todo { + v, err := tc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (tc *TodoCreate) Exec(ctx context.Context) error { + _, err := tc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (tc *TodoCreate) ExecX(ctx context.Context) { + if err := tc.Exec(ctx); err != nil { + panic(err) + } +} + +// defaults sets the default values of the builder before save. +func (tc *TodoCreate) defaults() { + if _, ok := tc.mutation.CreatedAt(); !ok { + v := todo.DefaultCreatedAt() + tc.mutation.SetCreatedAt(v) + } + if _, ok := tc.mutation.VisibilityStatus(); !ok { + v := todo.DefaultVisibilityStatus + tc.mutation.SetVisibilityStatus(v) + } + if _, ok := tc.mutation.Priority(); !ok { + v := todo.DefaultPriority + tc.mutation.SetPriority(v) + } +} + +// check runs all checks and user-defined validators on the builder. +func (tc *TodoCreate) check() error { + if _, ok := tc.mutation.CreatedAt(); !ok { + return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Todo.created_at"`)} + } + if _, ok := tc.mutation.VisibilityStatus(); !ok { + return &ValidationError{Name: "visibility_status", err: errors.New(`ent: missing required field "Todo.visibility_status"`)} + } + if v, ok := tc.mutation.VisibilityStatus(); ok { + if err := todo.VisibilityStatusValidator(v); err != nil { + return &ValidationError{Name: "visibility_status", err: fmt.Errorf(`ent: validator failed for field "Todo.visibility_status": %w`, err)} + } + } + if _, ok := tc.mutation.Status(); !ok { + return &ValidationError{Name: "status", err: errors.New(`ent: missing required field "Todo.status"`)} + } + if v, ok := tc.mutation.Status(); ok { + if err := todo.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Todo.status": %w`, err)} + } + } + if _, ok := tc.mutation.Priority(); !ok { + return &ValidationError{Name: "priority", err: errors.New(`ent: missing required field "Todo.priority"`)} + } + if _, ok := tc.mutation.Text(); !ok { + return &ValidationError{Name: "text", err: errors.New(`ent: missing required field "Todo.text"`)} + } + if v, ok := tc.mutation.Text(); ok { + if err := todo.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Todo.text": %w`, err)} + } + } + return nil +} + +func (tc *TodoCreate) sqlSave(ctx context.Context) (*Todo, error) { + _node, _spec := tc.createSpec() + if err := sqlgraph.CreateNode(ctx, tc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (tc *TodoCreate) createSpec() (*Todo, *sqlgraph.CreateSpec) { + var ( + _node = &Todo{config: tc.config} + _spec = &sqlgraph.CreateSpec{ + Table: todo.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + } + ) + if value, ok := tc.mutation.CreatedAt(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeTime, + Value: value, + Column: todo.FieldCreatedAt, + }) + _node.CreatedAt = value + } + if value, ok := tc.mutation.VisibilityStatus(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: todo.FieldVisibilityStatus, + }) + _node.VisibilityStatus = value + } + if value, ok := tc.mutation.Status(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: todo.FieldStatus, + }) + _node.Status = value + } + if value, ok := tc.mutation.Priority(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: todo.FieldPriority, + }) + _node.Priority = value + } + if value, ok := tc.mutation.Text(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: todo.FieldText, + }) + _node.Text = value + } + if nodes := tc.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: todo.ParentTable, + Columns: []string{todo.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.todo_children = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := tc.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// TodoCreateBulk is the builder for creating many Todo entities in bulk. +type TodoCreateBulk struct { + config + builders []*TodoCreate +} + +// Save creates the Todo entities in the database. +func (tcb *TodoCreateBulk) Save(ctx context.Context) ([]*Todo, error) { + specs := make([]*sqlgraph.CreateSpec, len(tcb.builders)) + nodes := make([]*Todo, len(tcb.builders)) + mutators := make([]Mutator, len(tcb.builders)) + for i := range tcb.builders { + func(i int, root context.Context) { + builder := tcb.builders[i] + builder.defaults() + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*TodoMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, tcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, tcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, tcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (tcb *TodoCreateBulk) SaveX(ctx context.Context) []*Todo { + v, err := tcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (tcb *TodoCreateBulk) Exec(ctx context.Context) error { + _, err := tcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (tcb *TodoCreateBulk) ExecX(ctx context.Context) { + if err := tcb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/entgql/internal/todoplugin/ent/todo_delete.go b/entgql/internal/todoplugin/ent/todo_delete.go new file mode 100644 index 000000000..18255b890 --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo_delete.go @@ -0,0 +1,125 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// TodoDelete is the builder for deleting a Todo entity. +type TodoDelete struct { + config + hooks []Hook + mutation *TodoMutation +} + +// Where appends a list predicates to the TodoDelete builder. +func (td *TodoDelete) Where(ps ...predicate.Todo) *TodoDelete { + td.mutation.Where(ps...) + return td +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (td *TodoDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(td.hooks) == 0 { + affected, err = td.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*TodoMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + td.mutation = mutation + affected, err = td.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(td.hooks) - 1; i >= 0; i-- { + if td.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = td.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, td.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (td *TodoDelete) ExecX(ctx context.Context) int { + n, err := td.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (td *TodoDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: todo.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + if ps := td.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, td.driver, _spec) +} + +// TodoDeleteOne is the builder for deleting a single Todo entity. +type TodoDeleteOne struct { + td *TodoDelete +} + +// Exec executes the deletion query. +func (tdo *TodoDeleteOne) Exec(ctx context.Context) error { + n, err := tdo.td.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{todo.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (tdo *TodoDeleteOne) ExecX(ctx context.Context) { + tdo.td.ExecX(ctx) +} diff --git a/entgql/internal/todoplugin/ent/todo_query.go b/entgql/internal/todoplugin/ent/todo_query.go new file mode 100644 index 000000000..61ed4ebea --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo_query.go @@ -0,0 +1,1078 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "database/sql/driver" + "errors" + "fmt" + "math" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// TodoQuery is the builder for querying Todo entities. +type TodoQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.Todo + // eager-loading edges. + withParent *TodoQuery + withChildren *TodoQuery + withFKs bool + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the TodoQuery builder. +func (tq *TodoQuery) Where(ps ...predicate.Todo) *TodoQuery { + tq.predicates = append(tq.predicates, ps...) + return tq +} + +// Limit adds a limit step to the query. +func (tq *TodoQuery) Limit(limit int) *TodoQuery { + tq.limit = &limit + return tq +} + +// Offset adds an offset step to the query. +func (tq *TodoQuery) Offset(offset int) *TodoQuery { + tq.offset = &offset + return tq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (tq *TodoQuery) Unique(unique bool) *TodoQuery { + tq.unique = &unique + return tq +} + +// Order adds an order step to the query. +func (tq *TodoQuery) Order(o ...OrderFunc) *TodoQuery { + tq.order = append(tq.order, o...) + return tq +} + +// QueryParent chains the current query on the "parent" edge. +func (tq *TodoQuery) QueryParent() *TodoQuery { + query := &TodoQuery{config: tq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := tq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(todo.Table, todo.FieldID, selector), + sqlgraph.To(todo.Table, todo.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, todo.ParentTable, todo.ParentColumn), + ) + fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryChildren chains the current query on the "children" edge. +func (tq *TodoQuery) QueryChildren() *TodoQuery { + query := &TodoQuery{config: tq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := tq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(todo.Table, todo.FieldID, selector), + sqlgraph.To(todo.Table, todo.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, todo.ChildrenTable, todo.ChildrenColumn), + ) + fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first Todo entity from the query. +// Returns a *NotFoundError when no Todo was found. +func (tq *TodoQuery) First(ctx context.Context) (*Todo, error) { + nodes, err := tq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{todo.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (tq *TodoQuery) FirstX(ctx context.Context) *Todo { + node, err := tq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first Todo ID from the query. +// Returns a *NotFoundError when no Todo ID was found. +func (tq *TodoQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = tq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{todo.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (tq *TodoQuery) FirstIDX(ctx context.Context) int { + id, err := tq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single Todo entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one Todo entity is not found. +// Returns a *NotFoundError when no Todo entities are found. +func (tq *TodoQuery) Only(ctx context.Context) (*Todo, error) { + nodes, err := tq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{todo.Label} + default: + return nil, &NotSingularError{todo.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (tq *TodoQuery) OnlyX(ctx context.Context) *Todo { + node, err := tq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only Todo ID in the query. +// Returns a *NotSingularError when exactly one Todo ID is not found. +// Returns a *NotFoundError when no entities are found. +func (tq *TodoQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = tq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{todo.Label} + default: + err = &NotSingularError{todo.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (tq *TodoQuery) OnlyIDX(ctx context.Context) int { + id, err := tq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Todos. +func (tq *TodoQuery) All(ctx context.Context) ([]*Todo, error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + return tq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (tq *TodoQuery) AllX(ctx context.Context) []*Todo { + nodes, err := tq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of Todo IDs. +func (tq *TodoQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := tq.Select(todo.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (tq *TodoQuery) IDsX(ctx context.Context) []int { + ids, err := tq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (tq *TodoQuery) Count(ctx context.Context) (int, error) { + if err := tq.prepareQuery(ctx); err != nil { + return 0, err + } + return tq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (tq *TodoQuery) CountX(ctx context.Context) int { + count, err := tq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (tq *TodoQuery) Exist(ctx context.Context) (bool, error) { + if err := tq.prepareQuery(ctx); err != nil { + return false, err + } + return tq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (tq *TodoQuery) ExistX(ctx context.Context) bool { + exist, err := tq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the TodoQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (tq *TodoQuery) Clone() *TodoQuery { + if tq == nil { + return nil + } + return &TodoQuery{ + config: tq.config, + limit: tq.limit, + offset: tq.offset, + order: append([]OrderFunc{}, tq.order...), + predicates: append([]predicate.Todo{}, tq.predicates...), + withParent: tq.withParent.Clone(), + withChildren: tq.withChildren.Clone(), + // clone intermediate query. + sql: tq.sql.Clone(), + path: tq.path, + } +} + +// WithParent tells the query-builder to eager-load the nodes that are connected to +// the "parent" edge. The optional arguments are used to configure the query builder of the edge. +func (tq *TodoQuery) WithParent(opts ...func(*TodoQuery)) *TodoQuery { + query := &TodoQuery{config: tq.config} + for _, opt := range opts { + opt(query) + } + tq.withParent = query + return tq +} + +// WithChildren tells the query-builder to eager-load the nodes that are connected to +// the "children" edge. The optional arguments are used to configure the query builder of the edge. +func (tq *TodoQuery) WithChildren(opts ...func(*TodoQuery)) *TodoQuery { + query := &TodoQuery{config: tq.config} + for _, opt := range opts { + opt(query) + } + tq.withChildren = query + return tq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.Todo.Query(). +// GroupBy(todo.FieldCreatedAt). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (tq *TodoQuery) GroupBy(field string, fields ...string) *TodoGroupBy { + group := &TodoGroupBy{config: tq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + return tq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// CreatedAt time.Time `json:"created_at,omitempty"` +// } +// +// client.Todo.Query(). +// Select(todo.FieldCreatedAt). +// Scan(ctx, &v) +// +func (tq *TodoQuery) Select(fields ...string) *TodoSelect { + tq.fields = append(tq.fields, fields...) + return &TodoSelect{TodoQuery: tq} +} + +func (tq *TodoQuery) prepareQuery(ctx context.Context) error { + for _, f := range tq.fields { + if !todo.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if tq.path != nil { + prev, err := tq.path(ctx) + if err != nil { + return err + } + tq.sql = prev + } + return nil +} + +func (tq *TodoQuery) sqlAll(ctx context.Context) ([]*Todo, error) { + var ( + nodes = []*Todo{} + withFKs = tq.withFKs + _spec = tq.querySpec() + loadedTypes = [2]bool{ + tq.withParent != nil, + tq.withChildren != nil, + } + ) + if tq.withParent != nil { + withFKs = true + } + if withFKs { + _spec.Node.Columns = append(_spec.Node.Columns, todo.ForeignKeys...) + } + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &Todo{config: tq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, tq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + + if query := tq.withParent; query != nil { + ids := make([]int, 0, len(nodes)) + nodeids := make(map[int][]*Todo) + for i := range nodes { + if nodes[i].todo_children == nil { + continue + } + fk := *nodes[i].todo_children + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(todo.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "todo_children" returned %v`, n.ID) + } + for i := range nodes { + nodes[i].Edges.Parent = n + } + } + } + + if query := tq.withChildren; query != nil { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int]*Todo) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + nodes[i].Edges.Children = []*Todo{} + } + query.withFKs = true + query.Where(predicate.Todo(func(s *sql.Selector) { + s.Where(sql.InValues(todo.ChildrenColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, n := range neighbors { + fk := n.todo_children + if fk == nil { + return nil, fmt.Errorf(`foreign-key "todo_children" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return nil, fmt.Errorf(`unexpected foreign-key "todo_children" returned %v for node %v`, *fk, n.ID) + } + node.Edges.Children = append(node.Edges.Children, n) + } + } + + return nodes, nil +} + +func (tq *TodoQuery) sqlCount(ctx context.Context) (int, error) { + _spec := tq.querySpec() + _spec.Node.Columns = tq.fields + if len(tq.fields) > 0 { + _spec.Unique = tq.unique != nil && *tq.unique + } + return sqlgraph.CountNodes(ctx, tq.driver, _spec) +} + +func (tq *TodoQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := tq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (tq *TodoQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: todo.Table, + Columns: todo.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + From: tq.sql, + Unique: true, + } + if unique := tq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := tq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, todo.FieldID) + for i := range fields { + if fields[i] != todo.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := tq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := tq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := tq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := tq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (tq *TodoQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(tq.driver.Dialect()) + t1 := builder.Table(todo.Table) + columns := tq.fields + if len(columns) == 0 { + columns = todo.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if tq.sql != nil { + selector = tq.sql + selector.Select(selector.Columns(columns...)...) + } + if tq.unique != nil && *tq.unique { + selector.Distinct() + } + for _, p := range tq.predicates { + p(selector) + } + for _, p := range tq.order { + p(selector) + } + if offset := tq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := tq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// TodoGroupBy is the group-by builder for Todo entities. +type TodoGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (tgb *TodoGroupBy) Aggregate(fns ...AggregateFunc) *TodoGroupBy { + tgb.fns = append(tgb.fns, fns...) + return tgb +} + +// Scan applies the group-by query and scans the result into the given value. +func (tgb *TodoGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := tgb.path(ctx) + if err != nil { + return err + } + tgb.sql = query + return tgb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (tgb *TodoGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := tgb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(tgb.fields) > 1 { + return nil, errors.New("ent: TodoGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := tgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (tgb *TodoGroupBy) StringsX(ctx context.Context) []string { + v, err := tgb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = tgb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (tgb *TodoGroupBy) StringX(ctx context.Context) string { + v, err := tgb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(tgb.fields) > 1 { + return nil, errors.New("ent: TodoGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := tgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (tgb *TodoGroupBy) IntsX(ctx context.Context) []int { + v, err := tgb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = tgb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (tgb *TodoGroupBy) IntX(ctx context.Context) int { + v, err := tgb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(tgb.fields) > 1 { + return nil, errors.New("ent: TodoGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := tgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (tgb *TodoGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := tgb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = tgb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (tgb *TodoGroupBy) Float64X(ctx context.Context) float64 { + v, err := tgb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(tgb.fields) > 1 { + return nil, errors.New("ent: TodoGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := tgb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (tgb *TodoGroupBy) BoolsX(ctx context.Context) []bool { + v, err := tgb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (tgb *TodoGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = tgb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (tgb *TodoGroupBy) BoolX(ctx context.Context) bool { + v, err := tgb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (tgb *TodoGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range tgb.fields { + if !todo.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := tgb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := tgb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (tgb *TodoGroupBy) sqlQuery() *sql.Selector { + selector := tgb.sql.Select() + aggregation := make([]string, 0, len(tgb.fns)) + for _, fn := range tgb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(tgb.fields)+len(tgb.fns)) + for _, f := range tgb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(tgb.fields...)...) +} + +// TodoSelect is the builder for selecting fields of Todo entities. +type TodoSelect struct { + *TodoQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (ts *TodoSelect) Scan(ctx context.Context, v interface{}) error { + if err := ts.prepareQuery(ctx); err != nil { + return err + } + ts.sql = ts.TodoQuery.sqlQuery(ctx) + return ts.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (ts *TodoSelect) ScanX(ctx context.Context, v interface{}) { + if err := ts.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Strings(ctx context.Context) ([]string, error) { + if len(ts.fields) > 1 { + return nil, errors.New("ent: TodoSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := ts.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (ts *TodoSelect) StringsX(ctx context.Context) []string { + v, err := ts.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = ts.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoSelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (ts *TodoSelect) StringX(ctx context.Context) string { + v, err := ts.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Ints(ctx context.Context) ([]int, error) { + if len(ts.fields) > 1 { + return nil, errors.New("ent: TodoSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := ts.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (ts *TodoSelect) IntsX(ctx context.Context) []int { + v, err := ts.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = ts.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoSelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (ts *TodoSelect) IntX(ctx context.Context) int { + v, err := ts.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(ts.fields) > 1 { + return nil, errors.New("ent: TodoSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := ts.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (ts *TodoSelect) Float64sX(ctx context.Context) []float64 { + v, err := ts.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = ts.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoSelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (ts *TodoSelect) Float64X(ctx context.Context) float64 { + v, err := ts.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Bools(ctx context.Context) ([]bool, error) { + if len(ts.fields) > 1 { + return nil, errors.New("ent: TodoSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := ts.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (ts *TodoSelect) BoolsX(ctx context.Context) []bool { + v, err := ts.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (ts *TodoSelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = ts.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{todo.Label} + default: + err = fmt.Errorf("ent: TodoSelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (ts *TodoSelect) BoolX(ctx context.Context) bool { + v, err := ts.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (ts *TodoSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := ts.sql.Query() + if err := ts.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/entgql/internal/todoplugin/ent/todo_update.go b/entgql/internal/todoplugin/ent/todo_update.go new file mode 100644 index 000000000..a0a1ef2b5 --- /dev/null +++ b/entgql/internal/todoplugin/ent/todo_update.go @@ -0,0 +1,769 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// TodoUpdate is the builder for updating Todo entities. +type TodoUpdate struct { + config + hooks []Hook + mutation *TodoMutation +} + +// Where appends a list predicates to the TodoUpdate builder. +func (tu *TodoUpdate) Where(ps ...predicate.Todo) *TodoUpdate { + tu.mutation.Where(ps...) + return tu +} + +// SetVisibilityStatus sets the "visibility_status" field. +func (tu *TodoUpdate) SetVisibilityStatus(ts todo.VisibilityStatus) *TodoUpdate { + tu.mutation.SetVisibilityStatus(ts) + return tu +} + +// SetNillableVisibilityStatus sets the "visibility_status" field if the given value is not nil. +func (tu *TodoUpdate) SetNillableVisibilityStatus(ts *todo.VisibilityStatus) *TodoUpdate { + if ts != nil { + tu.SetVisibilityStatus(*ts) + } + return tu +} + +// SetStatus sets the "status" field. +func (tu *TodoUpdate) SetStatus(t todo.Status) *TodoUpdate { + tu.mutation.SetStatus(t) + return tu +} + +// SetPriority sets the "priority" field. +func (tu *TodoUpdate) SetPriority(i int) *TodoUpdate { + tu.mutation.ResetPriority() + tu.mutation.SetPriority(i) + return tu +} + +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (tu *TodoUpdate) SetNillablePriority(i *int) *TodoUpdate { + if i != nil { + tu.SetPriority(*i) + } + return tu +} + +// AddPriority adds i to the "priority" field. +func (tu *TodoUpdate) AddPriority(i int) *TodoUpdate { + tu.mutation.AddPriority(i) + return tu +} + +// SetText sets the "text" field. +func (tu *TodoUpdate) SetText(s string) *TodoUpdate { + tu.mutation.SetText(s) + return tu +} + +// SetParentID sets the "parent" edge to the Todo entity by ID. +func (tu *TodoUpdate) SetParentID(id int) *TodoUpdate { + tu.mutation.SetParentID(id) + return tu +} + +// SetNillableParentID sets the "parent" edge to the Todo entity by ID if the given value is not nil. +func (tu *TodoUpdate) SetNillableParentID(id *int) *TodoUpdate { + if id != nil { + tu = tu.SetParentID(*id) + } + return tu +} + +// SetParent sets the "parent" edge to the Todo entity. +func (tu *TodoUpdate) SetParent(t *Todo) *TodoUpdate { + return tu.SetParentID(t.ID) +} + +// AddChildIDs adds the "children" edge to the Todo entity by IDs. +func (tu *TodoUpdate) AddChildIDs(ids ...int) *TodoUpdate { + tu.mutation.AddChildIDs(ids...) + return tu +} + +// AddChildren adds the "children" edges to the Todo entity. +func (tu *TodoUpdate) AddChildren(t ...*Todo) *TodoUpdate { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return tu.AddChildIDs(ids...) +} + +// Mutation returns the TodoMutation object of the builder. +func (tu *TodoUpdate) Mutation() *TodoMutation { + return tu.mutation +} + +// ClearParent clears the "parent" edge to the Todo entity. +func (tu *TodoUpdate) ClearParent() *TodoUpdate { + tu.mutation.ClearParent() + return tu +} + +// ClearChildren clears all "children" edges to the Todo entity. +func (tu *TodoUpdate) ClearChildren() *TodoUpdate { + tu.mutation.ClearChildren() + return tu +} + +// RemoveChildIDs removes the "children" edge to Todo entities by IDs. +func (tu *TodoUpdate) RemoveChildIDs(ids ...int) *TodoUpdate { + tu.mutation.RemoveChildIDs(ids...) + return tu +} + +// RemoveChildren removes "children" edges to Todo entities. +func (tu *TodoUpdate) RemoveChildren(t ...*Todo) *TodoUpdate { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return tu.RemoveChildIDs(ids...) +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (tu *TodoUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(tu.hooks) == 0 { + if err = tu.check(); err != nil { + return 0, err + } + affected, err = tu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*TodoMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = tu.check(); err != nil { + return 0, err + } + tu.mutation = mutation + affected, err = tu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(tu.hooks) - 1; i >= 0; i-- { + if tu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = tu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, tu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (tu *TodoUpdate) SaveX(ctx context.Context) int { + affected, err := tu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (tu *TodoUpdate) Exec(ctx context.Context) error { + _, err := tu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (tu *TodoUpdate) ExecX(ctx context.Context) { + if err := tu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (tu *TodoUpdate) check() error { + if v, ok := tu.mutation.VisibilityStatus(); ok { + if err := todo.VisibilityStatusValidator(v); err != nil { + return &ValidationError{Name: "visibility_status", err: fmt.Errorf(`ent: validator failed for field "Todo.visibility_status": %w`, err)} + } + } + if v, ok := tu.mutation.Status(); ok { + if err := todo.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Todo.status": %w`, err)} + } + } + if v, ok := tu.mutation.Text(); ok { + if err := todo.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Todo.text": %w`, err)} + } + } + return nil +} + +func (tu *TodoUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: todo.Table, + Columns: todo.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + if ps := tu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := tu.mutation.VisibilityStatus(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: todo.FieldVisibilityStatus, + }) + } + if value, ok := tu.mutation.Status(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: todo.FieldStatus, + }) + } + if value, ok := tu.mutation.Priority(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: todo.FieldPriority, + }) + } + if value, ok := tu.mutation.AddedPriority(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: todo.FieldPriority, + }) + } + if value, ok := tu.mutation.Text(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: todo.FieldText, + }) + } + if tu.mutation.ParentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: todo.ParentTable, + Columns: []string{todo.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: todo.ParentTable, + Columns: []string{todo.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if tu.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !tu.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if n, err = sqlgraph.UpdateNodes(ctx, tu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{todo.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// TodoUpdateOne is the builder for updating a single Todo entity. +type TodoUpdateOne struct { + config + fields []string + hooks []Hook + mutation *TodoMutation +} + +// SetVisibilityStatus sets the "visibility_status" field. +func (tuo *TodoUpdateOne) SetVisibilityStatus(ts todo.VisibilityStatus) *TodoUpdateOne { + tuo.mutation.SetVisibilityStatus(ts) + return tuo +} + +// SetNillableVisibilityStatus sets the "visibility_status" field if the given value is not nil. +func (tuo *TodoUpdateOne) SetNillableVisibilityStatus(ts *todo.VisibilityStatus) *TodoUpdateOne { + if ts != nil { + tuo.SetVisibilityStatus(*ts) + } + return tuo +} + +// SetStatus sets the "status" field. +func (tuo *TodoUpdateOne) SetStatus(t todo.Status) *TodoUpdateOne { + tuo.mutation.SetStatus(t) + return tuo +} + +// SetPriority sets the "priority" field. +func (tuo *TodoUpdateOne) SetPriority(i int) *TodoUpdateOne { + tuo.mutation.ResetPriority() + tuo.mutation.SetPriority(i) + return tuo +} + +// SetNillablePriority sets the "priority" field if the given value is not nil. +func (tuo *TodoUpdateOne) SetNillablePriority(i *int) *TodoUpdateOne { + if i != nil { + tuo.SetPriority(*i) + } + return tuo +} + +// AddPriority adds i to the "priority" field. +func (tuo *TodoUpdateOne) AddPriority(i int) *TodoUpdateOne { + tuo.mutation.AddPriority(i) + return tuo +} + +// SetText sets the "text" field. +func (tuo *TodoUpdateOne) SetText(s string) *TodoUpdateOne { + tuo.mutation.SetText(s) + return tuo +} + +// SetParentID sets the "parent" edge to the Todo entity by ID. +func (tuo *TodoUpdateOne) SetParentID(id int) *TodoUpdateOne { + tuo.mutation.SetParentID(id) + return tuo +} + +// SetNillableParentID sets the "parent" edge to the Todo entity by ID if the given value is not nil. +func (tuo *TodoUpdateOne) SetNillableParentID(id *int) *TodoUpdateOne { + if id != nil { + tuo = tuo.SetParentID(*id) + } + return tuo +} + +// SetParent sets the "parent" edge to the Todo entity. +func (tuo *TodoUpdateOne) SetParent(t *Todo) *TodoUpdateOne { + return tuo.SetParentID(t.ID) +} + +// AddChildIDs adds the "children" edge to the Todo entity by IDs. +func (tuo *TodoUpdateOne) AddChildIDs(ids ...int) *TodoUpdateOne { + tuo.mutation.AddChildIDs(ids...) + return tuo +} + +// AddChildren adds the "children" edges to the Todo entity. +func (tuo *TodoUpdateOne) AddChildren(t ...*Todo) *TodoUpdateOne { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return tuo.AddChildIDs(ids...) +} + +// Mutation returns the TodoMutation object of the builder. +func (tuo *TodoUpdateOne) Mutation() *TodoMutation { + return tuo.mutation +} + +// ClearParent clears the "parent" edge to the Todo entity. +func (tuo *TodoUpdateOne) ClearParent() *TodoUpdateOne { + tuo.mutation.ClearParent() + return tuo +} + +// ClearChildren clears all "children" edges to the Todo entity. +func (tuo *TodoUpdateOne) ClearChildren() *TodoUpdateOne { + tuo.mutation.ClearChildren() + return tuo +} + +// RemoveChildIDs removes the "children" edge to Todo entities by IDs. +func (tuo *TodoUpdateOne) RemoveChildIDs(ids ...int) *TodoUpdateOne { + tuo.mutation.RemoveChildIDs(ids...) + return tuo +} + +// RemoveChildren removes "children" edges to Todo entities. +func (tuo *TodoUpdateOne) RemoveChildren(t ...*Todo) *TodoUpdateOne { + ids := make([]int, len(t)) + for i := range t { + ids[i] = t[i].ID + } + return tuo.RemoveChildIDs(ids...) +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (tuo *TodoUpdateOne) Select(field string, fields ...string) *TodoUpdateOne { + tuo.fields = append([]string{field}, fields...) + return tuo +} + +// Save executes the query and returns the updated Todo entity. +func (tuo *TodoUpdateOne) Save(ctx context.Context) (*Todo, error) { + var ( + err error + node *Todo + ) + if len(tuo.hooks) == 0 { + if err = tuo.check(); err != nil { + return nil, err + } + node, err = tuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*TodoMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = tuo.check(); err != nil { + return nil, err + } + tuo.mutation = mutation + node, err = tuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(tuo.hooks) - 1; i >= 0; i-- { + if tuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = tuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, tuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (tuo *TodoUpdateOne) SaveX(ctx context.Context) *Todo { + node, err := tuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (tuo *TodoUpdateOne) Exec(ctx context.Context) error { + _, err := tuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (tuo *TodoUpdateOne) ExecX(ctx context.Context) { + if err := tuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (tuo *TodoUpdateOne) check() error { + if v, ok := tuo.mutation.VisibilityStatus(); ok { + if err := todo.VisibilityStatusValidator(v); err != nil { + return &ValidationError{Name: "visibility_status", err: fmt.Errorf(`ent: validator failed for field "Todo.visibility_status": %w`, err)} + } + } + if v, ok := tuo.mutation.Status(); ok { + if err := todo.StatusValidator(v); err != nil { + return &ValidationError{Name: "status", err: fmt.Errorf(`ent: validator failed for field "Todo.status": %w`, err)} + } + } + if v, ok := tuo.mutation.Text(); ok { + if err := todo.TextValidator(v); err != nil { + return &ValidationError{Name: "text", err: fmt.Errorf(`ent: validator failed for field "Todo.text": %w`, err)} + } + } + return nil +} + +func (tuo *TodoUpdateOne) sqlSave(ctx context.Context) (_node *Todo, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: todo.Table, + Columns: todo.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + id, ok := tuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Todo.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := tuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, todo.FieldID) + for _, f := range fields { + if !todo.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != todo.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := tuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := tuo.mutation.VisibilityStatus(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: todo.FieldVisibilityStatus, + }) + } + if value, ok := tuo.mutation.Status(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: todo.FieldStatus, + }) + } + if value, ok := tuo.mutation.Priority(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: todo.FieldPriority, + }) + } + if value, ok := tuo.mutation.AddedPriority(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: todo.FieldPriority, + }) + } + if value, ok := tuo.mutation.Text(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: todo.FieldText, + }) + } + if tuo.mutation.ParentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: todo.ParentTable, + Columns: []string{todo.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: todo.ParentTable, + Columns: []string{todo.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if tuo.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !tuo.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: todo.ChildrenTable, + Columns: []string{todo.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: todo.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + _node = &Todo{config: tuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, tuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{todo.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/entgql/internal/todoplugin/ent/tx.go b/entgql/internal/todoplugin/ent/tx.go new file mode 100644 index 000000000..300ec4c93 --- /dev/null +++ b/entgql/internal/todoplugin/ent/tx.go @@ -0,0 +1,230 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "sync" + + "entgo.io/ent/dialect" +) + +// Tx is a transactional client that is created by calling Client.Tx(). +type Tx struct { + config + // Category is the client for interacting with the Category builders. + Category *CategoryClient + // Todo is the client for interacting with the Todo builders. + Todo *TodoClient + // User is the client for interacting with the User builders. + User *UserClient + + // lazily loaded. + client *Client + clientOnce sync.Once + + // completion callbacks. + mu sync.Mutex + onCommit []CommitHook + onRollback []RollbackHook + + // ctx lives for the life of the transaction. It is + // the same context used by the underlying connection. + ctx context.Context +} + +type ( + // Committer is the interface that wraps the Committer method. + Committer interface { + Commit(context.Context, *Tx) error + } + + // The CommitFunc type is an adapter to allow the use of ordinary + // function as a Committer. If f is a function with the appropriate + // signature, CommitFunc(f) is a Committer that calls f. + CommitFunc func(context.Context, *Tx) error + + // CommitHook defines the "commit middleware". A function that gets a Committer + // and returns a Committer. For example: + // + // hook := func(next ent.Committer) ent.Committer { + // return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error { + // // Do some stuff before. + // if err := next.Commit(ctx, tx); err != nil { + // return err + // } + // // Do some stuff after. + // return nil + // }) + // } + // + CommitHook func(Committer) Committer +) + +// Commit calls f(ctx, m). +func (f CommitFunc) Commit(ctx context.Context, tx *Tx) error { + return f(ctx, tx) +} + +// Commit commits the transaction. +func (tx *Tx) Commit() error { + txDriver := tx.config.driver.(*txDriver) + var fn Committer = CommitFunc(func(context.Context, *Tx) error { + return txDriver.tx.Commit() + }) + tx.mu.Lock() + hooks := append([]CommitHook(nil), tx.onCommit...) + tx.mu.Unlock() + for i := len(hooks) - 1; i >= 0; i-- { + fn = hooks[i](fn) + } + return fn.Commit(tx.ctx, tx) +} + +// OnCommit adds a hook to call on commit. +func (tx *Tx) OnCommit(f CommitHook) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onCommit = append(tx.onCommit, f) +} + +type ( + // Rollbacker is the interface that wraps the Rollbacker method. + Rollbacker interface { + Rollback(context.Context, *Tx) error + } + + // The RollbackFunc type is an adapter to allow the use of ordinary + // function as a Rollbacker. If f is a function with the appropriate + // signature, RollbackFunc(f) is a Rollbacker that calls f. + RollbackFunc func(context.Context, *Tx) error + + // RollbackHook defines the "rollback middleware". A function that gets a Rollbacker + // and returns a Rollbacker. For example: + // + // hook := func(next ent.Rollbacker) ent.Rollbacker { + // return ent.RollbackFunc(func(ctx context.Context, tx *ent.Tx) error { + // // Do some stuff before. + // if err := next.Rollback(ctx, tx); err != nil { + // return err + // } + // // Do some stuff after. + // return nil + // }) + // } + // + RollbackHook func(Rollbacker) Rollbacker +) + +// Rollback calls f(ctx, m). +func (f RollbackFunc) Rollback(ctx context.Context, tx *Tx) error { + return f(ctx, tx) +} + +// Rollback rollbacks the transaction. +func (tx *Tx) Rollback() error { + txDriver := tx.config.driver.(*txDriver) + var fn Rollbacker = RollbackFunc(func(context.Context, *Tx) error { + return txDriver.tx.Rollback() + }) + tx.mu.Lock() + hooks := append([]RollbackHook(nil), tx.onRollback...) + tx.mu.Unlock() + for i := len(hooks) - 1; i >= 0; i-- { + fn = hooks[i](fn) + } + return fn.Rollback(tx.ctx, tx) +} + +// OnRollback adds a hook to call on rollback. +func (tx *Tx) OnRollback(f RollbackHook) { + tx.mu.Lock() + defer tx.mu.Unlock() + tx.onRollback = append(tx.onRollback, f) +} + +// Client returns a Client that binds to current transaction. +func (tx *Tx) Client() *Client { + tx.clientOnce.Do(func() { + tx.client = &Client{config: tx.config} + tx.client.init() + }) + return tx.client +} + +func (tx *Tx) init() { + tx.Category = NewCategoryClient(tx.config) + tx.Todo = NewTodoClient(tx.config) + tx.User = NewUserClient(tx.config) +} + +// txDriver wraps the given dialect.Tx with a nop dialect.Driver implementation. +// The idea is to support transactions without adding any extra code to the builders. +// When a builder calls to driver.Tx(), it gets the same dialect.Tx instance. +// Commit and Rollback are nop for the internal builders and the user must call one +// of them in order to commit or rollback the transaction. +// +// If a closed transaction is embedded in one of the generated entities, and the entity +// applies a query, for example: Category.QueryXXX(), the query will be executed +// through the driver which created this transaction. +// +// Note that txDriver is not goroutine safe. +type txDriver struct { + // the driver we started the transaction from. + drv dialect.Driver + // tx is the underlying transaction. + tx dialect.Tx +} + +// newTx creates a new transactional driver. +func newTx(ctx context.Context, drv dialect.Driver) (*txDriver, error) { + tx, err := drv.Tx(ctx) + if err != nil { + return nil, err + } + return &txDriver{tx: tx, drv: drv}, nil +} + +// Tx returns the transaction wrapper (txDriver) to avoid Commit or Rollback calls +// from the internal builders. Should be called only by the internal builders. +func (tx *txDriver) Tx(context.Context) (dialect.Tx, error) { return tx, nil } + +// Dialect returns the dialect of the driver we started the transaction from. +func (tx *txDriver) Dialect() string { return tx.drv.Dialect() } + +// Close is a nop close. +func (*txDriver) Close() error { return nil } + +// Commit is a nop commit for the internal builders. +// User must call `Tx.Commit` in order to commit the transaction. +func (*txDriver) Commit() error { return nil } + +// Rollback is a nop rollback for the internal builders. +// User must call `Tx.Rollback` in order to rollback the transaction. +func (*txDriver) Rollback() error { return nil } + +// Exec calls tx.Exec. +func (tx *txDriver) Exec(ctx context.Context, query string, args, v interface{}) error { + return tx.tx.Exec(ctx, query, args, v) +} + +// Query calls tx.Query. +func (tx *txDriver) Query(ctx context.Context, query string, args, v interface{}) error { + return tx.tx.Query(ctx, query, args, v) +} + +var _ dialect.Driver = (*txDriver)(nil) diff --git a/entgql/internal/todoplugin/ent/user.go b/entgql/internal/todoplugin/ent/user.go new file mode 100644 index 000000000..78365993e --- /dev/null +++ b/entgql/internal/todoplugin/ent/user.go @@ -0,0 +1,147 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect/sql" +) + +// User is the model entity for the User schema. +type User struct { + config `json:"-"` + // ID of the ent. + ID int `json:"id,omitempty"` + // Username holds the value of the "username" field. + Username string `json:"username,omitempty"` + // Age holds the value of the "age" field. + Age int `json:"age,omitempty"` + // Amount holds the value of the "amount" field. + Amount schema.Amount `json:"amount,omitempty"` + // Role holds the value of the "role" field. + Role role.Role `json:"role,omitempty"` +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*User) scanValues(columns []string) ([]interface{}, error) { + values := make([]interface{}, len(columns)) + for i := range columns { + switch columns[i] { + case user.FieldAmount: + values[i] = new(sql.NullFloat64) + case user.FieldID, user.FieldAge: + values[i] = new(sql.NullInt64) + case user.FieldUsername, user.FieldRole: + values[i] = new(sql.NullString) + default: + return nil, fmt.Errorf("unexpected column %q for type User", columns[i]) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the User fields. +func (u *User) assignValues(columns []string, values []interface{}) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case user.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + u.ID = int(value.Int64) + case user.FieldUsername: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field username", values[i]) + } else if value.Valid { + u.Username = value.String + } + case user.FieldAge: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field age", values[i]) + } else if value.Valid { + u.Age = int(value.Int64) + } + case user.FieldAmount: + if value, ok := values[i].(*sql.NullFloat64); !ok { + return fmt.Errorf("unexpected type %T for field amount", values[i]) + } else if value.Valid { + u.Amount = schema.Amount(value.Float64) + } + case user.FieldRole: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field role", values[i]) + } else if value.Valid { + u.Role = role.Role(value.String) + } + } + } + return nil +} + +// Update returns a builder for updating this User. +// Note that you need to call User.Unwrap() before calling this method if this User +// was returned from a transaction, and the transaction was committed or rolled back. +func (u *User) Update() *UserUpdateOne { + return (&UserClient{config: u.config}).UpdateOne(u) +} + +// Unwrap unwraps the User entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (u *User) Unwrap() *User { + tx, ok := u.config.driver.(*txDriver) + if !ok { + panic("ent: User is not a transactional entity") + } + u.config.driver = tx.drv + return u +} + +// String implements the fmt.Stringer. +func (u *User) String() string { + var builder strings.Builder + builder.WriteString("User(") + builder.WriteString(fmt.Sprintf("id=%v", u.ID)) + builder.WriteString(", username=") + builder.WriteString(u.Username) + builder.WriteString(", age=") + builder.WriteString(fmt.Sprintf("%v", u.Age)) + builder.WriteString(", amount=") + builder.WriteString(fmt.Sprintf("%v", u.Amount)) + builder.WriteString(", role=") + builder.WriteString(fmt.Sprintf("%v", u.Role)) + builder.WriteByte(')') + return builder.String() +} + +// Users is a parsable slice of User. +type Users []*User + +func (u Users) config(cfg config) { + for _i := range u { + u[_i].config = cfg + } +} diff --git a/entgql/internal/todoplugin/ent/user/user.go b/entgql/internal/todoplugin/ent/user/user.go new file mode 100644 index 000000000..fdc45b587 --- /dev/null +++ b/entgql/internal/todoplugin/ent/user/user.go @@ -0,0 +1,77 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package user + +import ( + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "github.com/99designs/gqlgen/graphql" +) + +const ( + // Label holds the string label denoting the user type in the database. + Label = "user" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldUsername holds the string denoting the username field in the database. + FieldUsername = "username" + // FieldAge holds the string denoting the age field in the database. + FieldAge = "age" + // FieldAmount holds the string denoting the amount field in the database. + FieldAmount = "amount" + // FieldRole holds the string denoting the role field in the database. + FieldRole = "role" + // Table holds the table name of the user in the database. + Table = "users" +) + +// Columns holds all SQL columns for user fields. +var Columns = []string{ + FieldID, + FieldUsername, + FieldAge, + FieldAmount, + FieldRole, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +// RoleValidator is a validator for the "role" field enum values. It is called by the builders before save. +func RoleValidator(r role.Role) error { + switch r { + case "ADMIN", "USER", "UNKNOWN": + return nil + default: + return fmt.Errorf("user: invalid enum value for role field: %q", r) + } +} + +var ( + // role.Role must implement graphql.Marshaler. + _ graphql.Marshaler = role.Role("") + // role.Role must implement graphql.Unmarshaler. + _ graphql.Unmarshaler = (*role.Role)(nil) +) diff --git a/entgql/internal/todoplugin/ent/user/where.go b/entgql/internal/todoplugin/ent/user/where.go new file mode 100644 index 000000000..bba85a4d9 --- /dev/null +++ b/entgql/internal/todoplugin/ent/user/where.go @@ -0,0 +1,480 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package user + +import ( + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/ent/dialect/sql" +) + +// ID filters vertices based on their ID field. +func ID(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldID), id)) + }) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldID), id)) + }) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int) predicate.User { + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.In(s.C(FieldID), v...)) + }) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int) predicate.User { + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(ids) == 0 { + s.Where(sql.False()) + return + } + v := make([]interface{}, len(ids)) + for i := range v { + v[i] = ids[i] + } + s.Where(sql.NotIn(s.C(FieldID), v...)) + }) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldID), id)) + }) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldID), id)) + }) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldID), id)) + }) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldID), id)) + }) +} + +// Username applies equality check predicate on the "username" field. It's identical to UsernameEQ. +func Username(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldUsername), v)) + }) +} + +// Age applies equality check predicate on the "age" field. It's identical to AgeEQ. +func Age(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldAge), v)) + }) +} + +// Amount applies equality check predicate on the "amount" field. It's identical to AmountEQ. +func Amount(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldAmount), vc)) + }) +} + +// UsernameEQ applies the EQ predicate on the "username" field. +func UsernameEQ(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldUsername), v)) + }) +} + +// UsernameNEQ applies the NEQ predicate on the "username" field. +func UsernameNEQ(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldUsername), v)) + }) +} + +// UsernameIn applies the In predicate on the "username" field. +func UsernameIn(vs ...string) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldUsername), v...)) + }) +} + +// UsernameNotIn applies the NotIn predicate on the "username" field. +func UsernameNotIn(vs ...string) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldUsername), v...)) + }) +} + +// UsernameGT applies the GT predicate on the "username" field. +func UsernameGT(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldUsername), v)) + }) +} + +// UsernameGTE applies the GTE predicate on the "username" field. +func UsernameGTE(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldUsername), v)) + }) +} + +// UsernameLT applies the LT predicate on the "username" field. +func UsernameLT(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldUsername), v)) + }) +} + +// UsernameLTE applies the LTE predicate on the "username" field. +func UsernameLTE(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldUsername), v)) + }) +} + +// UsernameContains applies the Contains predicate on the "username" field. +func UsernameContains(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldUsername), v)) + }) +} + +// UsernameHasPrefix applies the HasPrefix predicate on the "username" field. +func UsernameHasPrefix(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldUsername), v)) + }) +} + +// UsernameHasSuffix applies the HasSuffix predicate on the "username" field. +func UsernameHasSuffix(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldUsername), v)) + }) +} + +// UsernameEqualFold applies the EqualFold predicate on the "username" field. +func UsernameEqualFold(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldUsername), v)) + }) +} + +// UsernameContainsFold applies the ContainsFold predicate on the "username" field. +func UsernameContainsFold(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldUsername), v)) + }) +} + +// AgeEQ applies the EQ predicate on the "age" field. +func AgeEQ(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldAge), v)) + }) +} + +// AgeNEQ applies the NEQ predicate on the "age" field. +func AgeNEQ(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldAge), v)) + }) +} + +// AgeIn applies the In predicate on the "age" field. +func AgeIn(vs ...int) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldAge), v...)) + }) +} + +// AgeNotIn applies the NotIn predicate on the "age" field. +func AgeNotIn(vs ...int) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldAge), v...)) + }) +} + +// AgeGT applies the GT predicate on the "age" field. +func AgeGT(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldAge), v)) + }) +} + +// AgeGTE applies the GTE predicate on the "age" field. +func AgeGTE(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldAge), v)) + }) +} + +// AgeLT applies the LT predicate on the "age" field. +func AgeLT(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldAge), v)) + }) +} + +// AgeLTE applies the LTE predicate on the "age" field. +func AgeLTE(v int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldAge), v)) + }) +} + +// AmountEQ applies the EQ predicate on the "amount" field. +func AmountEQ(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldAmount), vc)) + }) +} + +// AmountNEQ applies the NEQ predicate on the "amount" field. +func AmountNEQ(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldAmount), vc)) + }) +} + +// AmountIn applies the In predicate on the "amount" field. +func AmountIn(vs ...schema.Amount) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = float64(vs[i]) + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldAmount), v...)) + }) +} + +// AmountNotIn applies the NotIn predicate on the "amount" field. +func AmountNotIn(vs ...schema.Amount) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = float64(vs[i]) + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldAmount), v...)) + }) +} + +// AmountGT applies the GT predicate on the "amount" field. +func AmountGT(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldAmount), vc)) + }) +} + +// AmountGTE applies the GTE predicate on the "amount" field. +func AmountGTE(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldAmount), vc)) + }) +} + +// AmountLT applies the LT predicate on the "amount" field. +func AmountLT(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldAmount), vc)) + }) +} + +// AmountLTE applies the LTE predicate on the "amount" field. +func AmountLTE(v schema.Amount) predicate.User { + vc := float64(v) + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldAmount), vc)) + }) +} + +// RoleEQ applies the EQ predicate on the "role" field. +func RoleEQ(v role.Role) predicate.User { + vc := v + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldRole), vc)) + }) +} + +// RoleNEQ applies the NEQ predicate on the "role" field. +func RoleNEQ(v role.Role) predicate.User { + vc := v + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldRole), vc)) + }) +} + +// RoleIn applies the In predicate on the "role" field. +func RoleIn(vs ...role.Role) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldRole), v...)) + }) +} + +// RoleNotIn applies the NotIn predicate on the "role" field. +func RoleNotIn(vs ...role.Role) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldRole), v...)) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for _, p := range predicates { + p(s1) + } + s.Where(s1.P()) + }) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + s1 := s.Clone().SetP(nil) + for i, p := range predicates { + if i > 0 { + s1.Or() + } + p(s1) + } + s.Where(s1.P()) + }) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.User) predicate.User { + return predicate.User(func(s *sql.Selector) { + p(s.Not()) + }) +} diff --git a/entgql/internal/todoplugin/ent/user_create.go b/entgql/internal/todoplugin/ent/user_create.go new file mode 100644 index 000000000..50c6e7850 --- /dev/null +++ b/entgql/internal/todoplugin/ent/user_create.go @@ -0,0 +1,292 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// UserCreate is the builder for creating a User entity. +type UserCreate struct { + config + mutation *UserMutation + hooks []Hook +} + +// SetUsername sets the "username" field. +func (uc *UserCreate) SetUsername(s string) *UserCreate { + uc.mutation.SetUsername(s) + return uc +} + +// SetAge sets the "age" field. +func (uc *UserCreate) SetAge(i int) *UserCreate { + uc.mutation.SetAge(i) + return uc +} + +// SetAmount sets the "amount" field. +func (uc *UserCreate) SetAmount(s schema.Amount) *UserCreate { + uc.mutation.SetAmount(s) + return uc +} + +// SetRole sets the "role" field. +func (uc *UserCreate) SetRole(r role.Role) *UserCreate { + uc.mutation.SetRole(r) + return uc +} + +// Mutation returns the UserMutation object of the builder. +func (uc *UserCreate) Mutation() *UserMutation { + return uc.mutation +} + +// Save creates the User in the database. +func (uc *UserCreate) Save(ctx context.Context) (*User, error) { + var ( + err error + node *User + ) + if len(uc.hooks) == 0 { + if err = uc.check(); err != nil { + return nil, err + } + node, err = uc.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*UserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = uc.check(); err != nil { + return nil, err + } + uc.mutation = mutation + if node, err = uc.sqlSave(ctx); err != nil { + return nil, err + } + mutation.id = &node.ID + mutation.done = true + return node, err + }) + for i := len(uc.hooks) - 1; i >= 0; i-- { + if uc.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = uc.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, uc.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX calls Save and panics if Save returns an error. +func (uc *UserCreate) SaveX(ctx context.Context) *User { + v, err := uc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (uc *UserCreate) Exec(ctx context.Context) error { + _, err := uc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (uc *UserCreate) ExecX(ctx context.Context) { + if err := uc.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (uc *UserCreate) check() error { + if _, ok := uc.mutation.Username(); !ok { + return &ValidationError{Name: "username", err: errors.New(`ent: missing required field "User.username"`)} + } + if _, ok := uc.mutation.Age(); !ok { + return &ValidationError{Name: "age", err: errors.New(`ent: missing required field "User.age"`)} + } + if _, ok := uc.mutation.Amount(); !ok { + return &ValidationError{Name: "amount", err: errors.New(`ent: missing required field "User.amount"`)} + } + if _, ok := uc.mutation.Role(); !ok { + return &ValidationError{Name: "role", err: errors.New(`ent: missing required field "User.role"`)} + } + if v, ok := uc.mutation.Role(); ok { + if err := user.RoleValidator(v); err != nil { + return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "User.role": %w`, err)} + } + } + return nil +} + +func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) { + _node, _spec := uc.createSpec() + if err := sqlgraph.CreateNode(ctx, uc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + id := _spec.ID.Value.(int64) + _node.ID = int(id) + return _node, nil +} + +func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { + var ( + _node = &User{config: uc.config} + _spec = &sqlgraph.CreateSpec{ + Table: user.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + } + ) + if value, ok := uc.mutation.Username(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldUsername, + }) + _node.Username = value + } + if value, ok := uc.mutation.Age(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: user.FieldAge, + }) + _node.Age = value + } + if value, ok := uc.mutation.Amount(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: value, + Column: user.FieldAmount, + }) + _node.Amount = value + } + if value, ok := uc.mutation.Role(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: user.FieldRole, + }) + _node.Role = value + } + return _node, _spec +} + +// UserCreateBulk is the builder for creating many User entities in bulk. +type UserCreateBulk struct { + config + builders []*UserCreate +} + +// Save creates the User entities in the database. +func (ucb *UserCreateBulk) Save(ctx context.Context) ([]*User, error) { + specs := make([]*sqlgraph.CreateSpec, len(ucb.builders)) + nodes := make([]*User, len(ucb.builders)) + mutators := make([]Mutator, len(ucb.builders)) + for i := range ucb.builders { + func(i int, root context.Context) { + builder := ucb.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*UserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + nodes[i], specs[i] = builder.createSpec() + var err error + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, ucb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, ucb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + mutation.done = true + if specs[i].ID.Value != nil { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int(id) + } + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, ucb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (ucb *UserCreateBulk) SaveX(ctx context.Context) []*User { + v, err := ucb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ucb *UserCreateBulk) Exec(ctx context.Context) error { + _, err := ucb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ucb *UserCreateBulk) ExecX(ctx context.Context) { + if err := ucb.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/entgql/internal/todoplugin/ent/user_delete.go b/entgql/internal/todoplugin/ent/user_delete.go new file mode 100644 index 000000000..20b43b747 --- /dev/null +++ b/entgql/internal/todoplugin/ent/user_delete.go @@ -0,0 +1,125 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// UserDelete is the builder for deleting a User entity. +type UserDelete struct { + config + hooks []Hook + mutation *UserMutation +} + +// Where appends a list predicates to the UserDelete builder. +func (ud *UserDelete) Where(ps ...predicate.User) *UserDelete { + ud.mutation.Where(ps...) + return ud +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ud *UserDelete) Exec(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(ud.hooks) == 0 { + affected, err = ud.sqlExec(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*UserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + ud.mutation = mutation + affected, err = ud.sqlExec(ctx) + mutation.done = true + return affected, err + }) + for i := len(ud.hooks) - 1; i >= 0; i-- { + if ud.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = ud.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, ud.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ud *UserDelete) ExecX(ctx context.Context) int { + n, err := ud.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ud *UserDelete) sqlExec(ctx context.Context) (int, error) { + _spec := &sqlgraph.DeleteSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + if ps := ud.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return sqlgraph.DeleteNodes(ctx, ud.driver, _spec) +} + +// UserDeleteOne is the builder for deleting a single User entity. +type UserDeleteOne struct { + ud *UserDelete +} + +// Exec executes the deletion query. +func (udo *UserDeleteOne) Exec(ctx context.Context) error { + n, err := udo.ud.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{user.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (udo *UserDeleteOne) ExecX(ctx context.Context) { + udo.ud.ExecX(ctx) +} diff --git a/entgql/internal/todoplugin/ent/user_query.go b/entgql/internal/todoplugin/ent/user_query.go new file mode 100644 index 000000000..a55103983 --- /dev/null +++ b/entgql/internal/todoplugin/ent/user_query.go @@ -0,0 +1,934 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "math" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// UserQuery is the builder for querying User entities. +type UserQuery struct { + config + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.User + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the UserQuery builder. +func (uq *UserQuery) Where(ps ...predicate.User) *UserQuery { + uq.predicates = append(uq.predicates, ps...) + return uq +} + +// Limit adds a limit step to the query. +func (uq *UserQuery) Limit(limit int) *UserQuery { + uq.limit = &limit + return uq +} + +// Offset adds an offset step to the query. +func (uq *UserQuery) Offset(offset int) *UserQuery { + uq.offset = &offset + return uq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (uq *UserQuery) Unique(unique bool) *UserQuery { + uq.unique = &unique + return uq +} + +// Order adds an order step to the query. +func (uq *UserQuery) Order(o ...OrderFunc) *UserQuery { + uq.order = append(uq.order, o...) + return uq +} + +// First returns the first User entity from the query. +// Returns a *NotFoundError when no User was found. +func (uq *UserQuery) First(ctx context.Context) (*User, error) { + nodes, err := uq.Limit(1).All(ctx) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{user.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (uq *UserQuery) FirstX(ctx context.Context) *User { + node, err := uq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first User ID from the query. +// Returns a *NotFoundError when no User ID was found. +func (uq *UserQuery) FirstID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = uq.Limit(1).IDs(ctx); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{user.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (uq *UserQuery) FirstIDX(ctx context.Context) int { + id, err := uq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single User entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when exactly one User entity is not found. +// Returns a *NotFoundError when no User entities are found. +func (uq *UserQuery) Only(ctx context.Context) (*User, error) { + nodes, err := uq.Limit(2).All(ctx) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{user.Label} + default: + return nil, &NotSingularError{user.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (uq *UserQuery) OnlyX(ctx context.Context) *User { + node, err := uq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only User ID in the query. +// Returns a *NotSingularError when exactly one User ID is not found. +// Returns a *NotFoundError when no entities are found. +func (uq *UserQuery) OnlyID(ctx context.Context) (id int, err error) { + var ids []int + if ids, err = uq.Limit(2).IDs(ctx); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{user.Label} + default: + err = &NotSingularError{user.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (uq *UserQuery) OnlyIDX(ctx context.Context) int { + id, err := uq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of Users. +func (uq *UserQuery) All(ctx context.Context) ([]*User, error) { + if err := uq.prepareQuery(ctx); err != nil { + return nil, err + } + return uq.sqlAll(ctx) +} + +// AllX is like All, but panics if an error occurs. +func (uq *UserQuery) AllX(ctx context.Context) []*User { + nodes, err := uq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of User IDs. +func (uq *UserQuery) IDs(ctx context.Context) ([]int, error) { + var ids []int + if err := uq.Select(user.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (uq *UserQuery) IDsX(ctx context.Context) []int { + ids, err := uq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (uq *UserQuery) Count(ctx context.Context) (int, error) { + if err := uq.prepareQuery(ctx); err != nil { + return 0, err + } + return uq.sqlCount(ctx) +} + +// CountX is like Count, but panics if an error occurs. +func (uq *UserQuery) CountX(ctx context.Context) int { + count, err := uq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (uq *UserQuery) Exist(ctx context.Context) (bool, error) { + if err := uq.prepareQuery(ctx); err != nil { + return false, err + } + return uq.sqlExist(ctx) +} + +// ExistX is like Exist, but panics if an error occurs. +func (uq *UserQuery) ExistX(ctx context.Context) bool { + exist, err := uq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the UserQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (uq *UserQuery) Clone() *UserQuery { + if uq == nil { + return nil + } + return &UserQuery{ + config: uq.config, + limit: uq.limit, + offset: uq.offset, + order: append([]OrderFunc{}, uq.order...), + predicates: append([]predicate.User{}, uq.predicates...), + // clone intermediate query. + sql: uq.sql.Clone(), + path: uq.path, + } +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// Username string `json:"username,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.User.Query(). +// GroupBy(user.FieldUsername). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +// +func (uq *UserQuery) GroupBy(field string, fields ...string) *UserGroupBy { + group := &UserGroupBy{config: uq.config} + group.fields = append([]string{field}, fields...) + group.path = func(ctx context.Context) (prev *sql.Selector, err error) { + if err := uq.prepareQuery(ctx); err != nil { + return nil, err + } + return uq.sqlQuery(ctx), nil + } + return group +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// Username string `json:"username,omitempty"` +// } +// +// client.User.Query(). +// Select(user.FieldUsername). +// Scan(ctx, &v) +// +func (uq *UserQuery) Select(fields ...string) *UserSelect { + uq.fields = append(uq.fields, fields...) + return &UserSelect{UserQuery: uq} +} + +func (uq *UserQuery) prepareQuery(ctx context.Context) error { + for _, f := range uq.fields { + if !user.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if uq.path != nil { + prev, err := uq.path(ctx) + if err != nil { + return err + } + uq.sql = prev + } + return nil +} + +func (uq *UserQuery) sqlAll(ctx context.Context) ([]*User, error) { + var ( + nodes = []*User{} + _spec = uq.querySpec() + ) + _spec.ScanValues = func(columns []string) ([]interface{}, error) { + node := &User{config: uq.config} + nodes = append(nodes, node) + return node.scanValues(columns) + } + _spec.Assign = func(columns []string, values []interface{}) error { + if len(nodes) == 0 { + return fmt.Errorf("ent: Assign called without calling ScanValues") + } + node := nodes[len(nodes)-1] + return node.assignValues(columns, values) + } + if err := sqlgraph.QueryNodes(ctx, uq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + return nodes, nil +} + +func (uq *UserQuery) sqlCount(ctx context.Context) (int, error) { + _spec := uq.querySpec() + _spec.Node.Columns = uq.fields + if len(uq.fields) > 0 { + _spec.Unique = uq.unique != nil && *uq.unique + } + return sqlgraph.CountNodes(ctx, uq.driver, _spec) +} + +func (uq *UserQuery) sqlExist(ctx context.Context) (bool, error) { + n, err := uq.sqlCount(ctx) + if err != nil { + return false, fmt.Errorf("ent: check existence: %w", err) + } + return n > 0, nil +} + +func (uq *UserQuery) querySpec() *sqlgraph.QuerySpec { + _spec := &sqlgraph.QuerySpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + From: uq.sql, + Unique: true, + } + if unique := uq.unique; unique != nil { + _spec.Unique = *unique + } + if fields := uq.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, user.FieldID) + for i := range fields { + if fields[i] != user.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + } + if ps := uq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := uq.limit; limit != nil { + _spec.Limit = *limit + } + if offset := uq.offset; offset != nil { + _spec.Offset = *offset + } + if ps := uq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (uq *UserQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(uq.driver.Dialect()) + t1 := builder.Table(user.Table) + columns := uq.fields + if len(columns) == 0 { + columns = user.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if uq.sql != nil { + selector = uq.sql + selector.Select(selector.Columns(columns...)...) + } + if uq.unique != nil && *uq.unique { + selector.Distinct() + } + for _, p := range uq.predicates { + p(selector) + } + for _, p := range uq.order { + p(selector) + } + if offset := uq.offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := uq.limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// UserGroupBy is the group-by builder for User entities. +type UserGroupBy struct { + config + fields []string + fns []AggregateFunc + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (ugb *UserGroupBy) Aggregate(fns ...AggregateFunc) *UserGroupBy { + ugb.fns = append(ugb.fns, fns...) + return ugb +} + +// Scan applies the group-by query and scans the result into the given value. +func (ugb *UserGroupBy) Scan(ctx context.Context, v interface{}) error { + query, err := ugb.path(ctx) + if err != nil { + return err + } + ugb.sql = query + return ugb.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (ugb *UserGroupBy) ScanX(ctx context.Context, v interface{}) { + if err := ugb.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from group-by. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Strings(ctx context.Context) ([]string, error) { + if len(ugb.fields) > 1 { + return nil, errors.New("ent: UserGroupBy.Strings is not achievable when grouping more than 1 field") + } + var v []string + if err := ugb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (ugb *UserGroupBy) StringsX(ctx context.Context) []string { + v, err := ugb.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = ugb.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserGroupBy.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (ugb *UserGroupBy) StringX(ctx context.Context) string { + v, err := ugb.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from group-by. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Ints(ctx context.Context) ([]int, error) { + if len(ugb.fields) > 1 { + return nil, errors.New("ent: UserGroupBy.Ints is not achievable when grouping more than 1 field") + } + var v []int + if err := ugb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (ugb *UserGroupBy) IntsX(ctx context.Context) []int { + v, err := ugb.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = ugb.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserGroupBy.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (ugb *UserGroupBy) IntX(ctx context.Context) int { + v, err := ugb.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from group-by. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Float64s(ctx context.Context) ([]float64, error) { + if len(ugb.fields) > 1 { + return nil, errors.New("ent: UserGroupBy.Float64s is not achievable when grouping more than 1 field") + } + var v []float64 + if err := ugb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (ugb *UserGroupBy) Float64sX(ctx context.Context) []float64 { + v, err := ugb.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = ugb.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserGroupBy.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (ugb *UserGroupBy) Float64X(ctx context.Context) float64 { + v, err := ugb.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from group-by. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Bools(ctx context.Context) ([]bool, error) { + if len(ugb.fields) > 1 { + return nil, errors.New("ent: UserGroupBy.Bools is not achievable when grouping more than 1 field") + } + var v []bool + if err := ugb.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (ugb *UserGroupBy) BoolsX(ctx context.Context) []bool { + v, err := ugb.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a group-by query. +// It is only allowed when executing a group-by query with one field. +func (ugb *UserGroupBy) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = ugb.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserGroupBy.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (ugb *UserGroupBy) BoolX(ctx context.Context) bool { + v, err := ugb.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (ugb *UserGroupBy) sqlScan(ctx context.Context, v interface{}) error { + for _, f := range ugb.fields { + if !user.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("invalid field %q for group-by", f)} + } + } + selector := ugb.sqlQuery() + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ugb.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +func (ugb *UserGroupBy) sqlQuery() *sql.Selector { + selector := ugb.sql.Select() + aggregation := make([]string, 0, len(ugb.fns)) + for _, fn := range ugb.fns { + aggregation = append(aggregation, fn(selector)) + } + // If no columns were selected in a custom aggregation function, the default + // selection is the fields used for "group-by", and the aggregation functions. + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(ugb.fields)+len(ugb.fns)) + for _, f := range ugb.fields { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + return selector.GroupBy(selector.Columns(ugb.fields...)...) +} + +// UserSelect is the builder for selecting fields of User entities. +type UserSelect struct { + *UserQuery + // intermediate query (i.e. traversal path). + sql *sql.Selector +} + +// Scan applies the selector query and scans the result into the given value. +func (us *UserSelect) Scan(ctx context.Context, v interface{}) error { + if err := us.prepareQuery(ctx); err != nil { + return err + } + us.sql = us.UserQuery.sqlQuery(ctx) + return us.sqlScan(ctx, v) +} + +// ScanX is like Scan, but panics if an error occurs. +func (us *UserSelect) ScanX(ctx context.Context, v interface{}) { + if err := us.Scan(ctx, v); err != nil { + panic(err) + } +} + +// Strings returns list of strings from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Strings(ctx context.Context) ([]string, error) { + if len(us.fields) > 1 { + return nil, errors.New("ent: UserSelect.Strings is not achievable when selecting more than 1 field") + } + var v []string + if err := us.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// StringsX is like Strings, but panics if an error occurs. +func (us *UserSelect) StringsX(ctx context.Context) []string { + v, err := us.Strings(ctx) + if err != nil { + panic(err) + } + return v +} + +// String returns a single string from a selector. It is only allowed when selecting one field. +func (us *UserSelect) String(ctx context.Context) (_ string, err error) { + var v []string + if v, err = us.Strings(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserSelect.Strings returned %d results when one was expected", len(v)) + } + return +} + +// StringX is like String, but panics if an error occurs. +func (us *UserSelect) StringX(ctx context.Context) string { + v, err := us.String(ctx) + if err != nil { + panic(err) + } + return v +} + +// Ints returns list of ints from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Ints(ctx context.Context) ([]int, error) { + if len(us.fields) > 1 { + return nil, errors.New("ent: UserSelect.Ints is not achievable when selecting more than 1 field") + } + var v []int + if err := us.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// IntsX is like Ints, but panics if an error occurs. +func (us *UserSelect) IntsX(ctx context.Context) []int { + v, err := us.Ints(ctx) + if err != nil { + panic(err) + } + return v +} + +// Int returns a single int from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Int(ctx context.Context) (_ int, err error) { + var v []int + if v, err = us.Ints(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserSelect.Ints returned %d results when one was expected", len(v)) + } + return +} + +// IntX is like Int, but panics if an error occurs. +func (us *UserSelect) IntX(ctx context.Context) int { + v, err := us.Int(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64s returns list of float64s from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Float64s(ctx context.Context) ([]float64, error) { + if len(us.fields) > 1 { + return nil, errors.New("ent: UserSelect.Float64s is not achievable when selecting more than 1 field") + } + var v []float64 + if err := us.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// Float64sX is like Float64s, but panics if an error occurs. +func (us *UserSelect) Float64sX(ctx context.Context) []float64 { + v, err := us.Float64s(ctx) + if err != nil { + panic(err) + } + return v +} + +// Float64 returns a single float64 from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Float64(ctx context.Context) (_ float64, err error) { + var v []float64 + if v, err = us.Float64s(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserSelect.Float64s returned %d results when one was expected", len(v)) + } + return +} + +// Float64X is like Float64, but panics if an error occurs. +func (us *UserSelect) Float64X(ctx context.Context) float64 { + v, err := us.Float64(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bools returns list of bools from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Bools(ctx context.Context) ([]bool, error) { + if len(us.fields) > 1 { + return nil, errors.New("ent: UserSelect.Bools is not achievable when selecting more than 1 field") + } + var v []bool + if err := us.Scan(ctx, &v); err != nil { + return nil, err + } + return v, nil +} + +// BoolsX is like Bools, but panics if an error occurs. +func (us *UserSelect) BoolsX(ctx context.Context) []bool { + v, err := us.Bools(ctx) + if err != nil { + panic(err) + } + return v +} + +// Bool returns a single bool from a selector. It is only allowed when selecting one field. +func (us *UserSelect) Bool(ctx context.Context) (_ bool, err error) { + var v []bool + if v, err = us.Bools(ctx); err != nil { + return + } + switch len(v) { + case 1: + return v[0], nil + case 0: + err = &NotFoundError{user.Label} + default: + err = fmt.Errorf("ent: UserSelect.Bools returned %d results when one was expected", len(v)) + } + return +} + +// BoolX is like Bool, but panics if an error occurs. +func (us *UserSelect) BoolX(ctx context.Context) bool { + v, err := us.Bool(ctx) + if err != nil { + panic(err) + } + return v +} + +func (us *UserSelect) sqlScan(ctx context.Context, v interface{}) error { + rows := &sql.Rows{} + query, args := us.sql.Query() + if err := us.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} diff --git a/entgql/internal/todoplugin/ent/user_update.go b/entgql/internal/todoplugin/ent/user_update.go new file mode 100644 index 000000000..c1aecd272 --- /dev/null +++ b/entgql/internal/todoplugin/ent/user_update.go @@ -0,0 +1,447 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by entc, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" + "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" +) + +// UserUpdate is the builder for updating User entities. +type UserUpdate struct { + config + hooks []Hook + mutation *UserMutation +} + +// Where appends a list predicates to the UserUpdate builder. +func (uu *UserUpdate) Where(ps ...predicate.User) *UserUpdate { + uu.mutation.Where(ps...) + return uu +} + +// SetUsername sets the "username" field. +func (uu *UserUpdate) SetUsername(s string) *UserUpdate { + uu.mutation.SetUsername(s) + return uu +} + +// SetAge sets the "age" field. +func (uu *UserUpdate) SetAge(i int) *UserUpdate { + uu.mutation.ResetAge() + uu.mutation.SetAge(i) + return uu +} + +// AddAge adds i to the "age" field. +func (uu *UserUpdate) AddAge(i int) *UserUpdate { + uu.mutation.AddAge(i) + return uu +} + +// SetAmount sets the "amount" field. +func (uu *UserUpdate) SetAmount(s schema.Amount) *UserUpdate { + uu.mutation.ResetAmount() + uu.mutation.SetAmount(s) + return uu +} + +// AddAmount adds s to the "amount" field. +func (uu *UserUpdate) AddAmount(s schema.Amount) *UserUpdate { + uu.mutation.AddAmount(s) + return uu +} + +// SetRole sets the "role" field. +func (uu *UserUpdate) SetRole(r role.Role) *UserUpdate { + uu.mutation.SetRole(r) + return uu +} + +// Mutation returns the UserMutation object of the builder. +func (uu *UserUpdate) Mutation() *UserMutation { + return uu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (uu *UserUpdate) Save(ctx context.Context) (int, error) { + var ( + err error + affected int + ) + if len(uu.hooks) == 0 { + if err = uu.check(); err != nil { + return 0, err + } + affected, err = uu.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*UserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = uu.check(); err != nil { + return 0, err + } + uu.mutation = mutation + affected, err = uu.sqlSave(ctx) + mutation.done = true + return affected, err + }) + for i := len(uu.hooks) - 1; i >= 0; i-- { + if uu.hooks[i] == nil { + return 0, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = uu.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, uu.mutation); err != nil { + return 0, err + } + } + return affected, err +} + +// SaveX is like Save, but panics if an error occurs. +func (uu *UserUpdate) SaveX(ctx context.Context) int { + affected, err := uu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (uu *UserUpdate) Exec(ctx context.Context) error { + _, err := uu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (uu *UserUpdate) ExecX(ctx context.Context) { + if err := uu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (uu *UserUpdate) check() error { + if v, ok := uu.mutation.Role(); ok { + if err := user.RoleValidator(v); err != nil { + return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "User.role": %w`, err)} + } + } + return nil +} + +func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + if ps := uu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := uu.mutation.Username(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldUsername, + }) + } + if value, ok := uu.mutation.Age(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: user.FieldAge, + }) + } + if value, ok := uu.mutation.AddedAge(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: user.FieldAge, + }) + } + if value, ok := uu.mutation.Amount(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: value, + Column: user.FieldAmount, + }) + } + if value, ok := uu.mutation.AddedAmount(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: value, + Column: user.FieldAmount, + }) + } + if value, ok := uu.mutation.Role(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: user.FieldRole, + }) + } + if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{user.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return 0, err + } + return n, nil +} + +// UserUpdateOne is the builder for updating a single User entity. +type UserUpdateOne struct { + config + fields []string + hooks []Hook + mutation *UserMutation +} + +// SetUsername sets the "username" field. +func (uuo *UserUpdateOne) SetUsername(s string) *UserUpdateOne { + uuo.mutation.SetUsername(s) + return uuo +} + +// SetAge sets the "age" field. +func (uuo *UserUpdateOne) SetAge(i int) *UserUpdateOne { + uuo.mutation.ResetAge() + uuo.mutation.SetAge(i) + return uuo +} + +// AddAge adds i to the "age" field. +func (uuo *UserUpdateOne) AddAge(i int) *UserUpdateOne { + uuo.mutation.AddAge(i) + return uuo +} + +// SetAmount sets the "amount" field. +func (uuo *UserUpdateOne) SetAmount(s schema.Amount) *UserUpdateOne { + uuo.mutation.ResetAmount() + uuo.mutation.SetAmount(s) + return uuo +} + +// AddAmount adds s to the "amount" field. +func (uuo *UserUpdateOne) AddAmount(s schema.Amount) *UserUpdateOne { + uuo.mutation.AddAmount(s) + return uuo +} + +// SetRole sets the "role" field. +func (uuo *UserUpdateOne) SetRole(r role.Role) *UserUpdateOne { + uuo.mutation.SetRole(r) + return uuo +} + +// Mutation returns the UserMutation object of the builder. +func (uuo *UserUpdateOne) Mutation() *UserMutation { + return uuo.mutation +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (uuo *UserUpdateOne) Select(field string, fields ...string) *UserUpdateOne { + uuo.fields = append([]string{field}, fields...) + return uuo +} + +// Save executes the query and returns the updated User entity. +func (uuo *UserUpdateOne) Save(ctx context.Context) (*User, error) { + var ( + err error + node *User + ) + if len(uuo.hooks) == 0 { + if err = uuo.check(); err != nil { + return nil, err + } + node, err = uuo.sqlSave(ctx) + } else { + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*UserMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err = uuo.check(); err != nil { + return nil, err + } + uuo.mutation = mutation + node, err = uuo.sqlSave(ctx) + mutation.done = true + return node, err + }) + for i := len(uuo.hooks) - 1; i >= 0; i-- { + if uuo.hooks[i] == nil { + return nil, fmt.Errorf("ent: uninitialized hook (forgotten import ent/runtime?)") + } + mut = uuo.hooks[i](mut) + } + if _, err := mut.Mutate(ctx, uuo.mutation); err != nil { + return nil, err + } + } + return node, err +} + +// SaveX is like Save, but panics if an error occurs. +func (uuo *UserUpdateOne) SaveX(ctx context.Context) *User { + node, err := uuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (uuo *UserUpdateOne) Exec(ctx context.Context) error { + _, err := uuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (uuo *UserUpdateOne) ExecX(ctx context.Context) { + if err := uuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (uuo *UserUpdateOne) check() error { + if v, ok := uuo.mutation.Role(); ok { + if err := user.RoleValidator(v); err != nil { + return &ValidationError{Name: "role", err: fmt.Errorf(`ent: validator failed for field "User.role": %w`, err)} + } + } + return nil +} + +func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) { + _spec := &sqlgraph.UpdateSpec{ + Node: &sqlgraph.NodeSpec{ + Table: user.Table, + Columns: user.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Column: user.FieldID, + }, + }, + } + id, ok := uuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "User.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := uuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, user.FieldID) + for _, f := range fields { + if !user.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != user.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := uuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if value, ok := uuo.mutation.Username(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldUsername, + }) + } + if value, ok := uuo.mutation.Age(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: user.FieldAge, + }) + } + if value, ok := uuo.mutation.AddedAge(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeInt, + Value: value, + Column: user.FieldAge, + }) + } + if value, ok := uuo.mutation.Amount(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: value, + Column: user.FieldAmount, + }) + } + if value, ok := uuo.mutation.AddedAmount(); ok { + _spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{ + Type: field.TypeFloat64, + Value: value, + Column: user.FieldAmount, + }) + } + if value, ok := uuo.mutation.Role(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeEnum, + Value: value, + Column: user.FieldRole, + }) + } + _node = &User{config: uuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, uuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{user.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{err.Error(), err} + } + return nil, err + } + return _node, nil +} diff --git a/entgql/internal/todoplugin/gen.go b/entgql/internal/todoplugin/gen.go new file mode 100644 index 000000000..583818b03 --- /dev/null +++ b/entgql/internal/todoplugin/gen.go @@ -0,0 +1,19 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package todoplugin + +//go:generate go run -mod=mod ./ent/entc.go +//go:generate go run -mod=mod ./cmd/entgqlgen.go -path ./ent/schema +//go:generate go run -mod=mod github.com/google/addlicense -c Facebook -y 2019-present ./ diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go new file mode 100644 index 000000000..14c15d4da --- /dev/null +++ b/entgql/internal/todoplugin/generated.go @@ -0,0 +1,5136 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package todoplugin + +import ( + "bytes" + "context" + "errors" + "fmt" + "strconv" + "sync" + "sync/atomic" + "time" + + "entgo.io/contrib/entgql/internal/todoplugin/ent" + "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "github.com/99designs/gqlgen/graphql" + "github.com/99designs/gqlgen/graphql/introspection" + 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 + Todo() TodoResolver + User() UserResolver +} + +type DirectiveRoot struct { + SomeDirective func(ctx context.Context, obj interface{}, next graphql.Resolver, stringArg *string, boolArg *bool) (res interface{}, err error) +} + +type ComplexityRoot struct { + Category struct { + ID func(childComplexity int) int + Strings func(childComplexity int) int + Text func(childComplexity int) int + } + + CategoryConfig struct { + MaxMembers func(childComplexity int) int + } + + Mutation struct { + ClearTodos func(childComplexity int) int + CreateTodo func(childComplexity int, todo TodoInput) int + } + + PageInfo struct { + EndCursor func(childComplexity int) int + HasNextPage func(childComplexity int) int + HasPreviousPage func(childComplexity int) int + StartCursor func(childComplexity int) int + } + + Query struct { + Node func(childComplexity int, id int) int + Nodes func(childComplexity int, ids []int) int + Todos func(childComplexity int, after *ent.Cursor, first *int, before *ent.Cursor, last *int, orderBy *ent.TodoOrder) int + } + + Todo struct { + Category func(childComplexity int) int + Children func(childComplexity int) int + CreatedAt func(childComplexity int) int + ID func(childComplexity int) int + Parent func(childComplexity int) int + Priority func(childComplexity int) int + Status func(childComplexity int) int + Text func(childComplexity int) int + } + + TodoConnection struct { + Edges func(childComplexity int) int + PageInfo func(childComplexity int) int + TotalCount func(childComplexity int) int + } + + TodoEdge struct { + Cursor func(childComplexity int) int + Node func(childComplexity int) int + } + + User struct { + Age func(childComplexity int) int + Amount func(childComplexity int) int + ID func(childComplexity int) int + Role func(childComplexity int) int + Username func(childComplexity int) int + } +} + +type MutationResolver interface { + CreateTodo(ctx context.Context, todo TodoInput) (*ent.Todo, error) + ClearTodos(ctx context.Context) (int, error) +} +type QueryResolver interface { + Node(ctx context.Context, id int) (ent.Noder, error) + Nodes(ctx context.Context, ids []int) ([]ent.Noder, error) + Todos(ctx context.Context, after *ent.Cursor, first *int, before *ent.Cursor, last *int, orderBy *ent.TodoOrder) (*ent.TodoConnection, error) +} +type TodoResolver interface { + Category(ctx context.Context, obj *ent.Todo) (*ent.Category, error) +} +type UserResolver interface { + Age(ctx context.Context, obj *ent.User) (float64, error) + Amount(ctx context.Context, obj *ent.User) (float64, 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} + _ = ec + switch typeName + "." + field { + + case "Category.id": + if e.complexity.Category.ID == nil { + break + } + + return e.complexity.Category.ID(childComplexity), true + + case "Category.strings": + if e.complexity.Category.Strings == nil { + break + } + + return e.complexity.Category.Strings(childComplexity), true + + case "Category.text": + if e.complexity.Category.Text == nil { + break + } + + return e.complexity.Category.Text(childComplexity), true + + case "CategoryConfig.maxMembers": + if e.complexity.CategoryConfig.MaxMembers == nil { + break + } + + return e.complexity.CategoryConfig.MaxMembers(childComplexity), true + + case "Mutation.clearTodos": + if e.complexity.Mutation.ClearTodos == nil { + break + } + + return e.complexity.Mutation.ClearTodos(childComplexity), true + + 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["todo"].(TodoInput)), true + + case "PageInfo.endCursor": + if e.complexity.PageInfo.EndCursor == nil { + break + } + + return e.complexity.PageInfo.EndCursor(childComplexity), true + + case "PageInfo.hasNextPage": + if e.complexity.PageInfo.HasNextPage == nil { + break + } + + return e.complexity.PageInfo.HasNextPage(childComplexity), true + + case "PageInfo.hasPreviousPage": + if e.complexity.PageInfo.HasPreviousPage == nil { + break + } + + return e.complexity.PageInfo.HasPreviousPage(childComplexity), true + + case "PageInfo.startCursor": + if e.complexity.PageInfo.StartCursor == nil { + break + } + + return e.complexity.PageInfo.StartCursor(childComplexity), true + + case "Query.node": + if e.complexity.Query.Node == nil { + break + } + + args, err := ec.field_Query_node_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Node(childComplexity, args["id"].(int)), true + + case "Query.nodes": + if e.complexity.Query.Nodes == nil { + break + } + + args, err := ec.field_Query_nodes_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Nodes(childComplexity, args["ids"].([]int)), true + + case "Query.todos": + if e.complexity.Query.Todos == nil { + break + } + + args, err := ec.field_Query_todos_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.Todos(childComplexity, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.TodoOrder)), true + + case "Todo.category": + if e.complexity.Todo.Category == nil { + break + } + + return e.complexity.Todo.Category(childComplexity), true + + case "Todo.children": + if e.complexity.Todo.Children == nil { + break + } + + return e.complexity.Todo.Children(childComplexity), true + + case "Todo.createdAt": + if e.complexity.Todo.CreatedAt == nil { + break + } + + return e.complexity.Todo.CreatedAt(childComplexity), true + + case "Todo.id": + if e.complexity.Todo.ID == nil { + break + } + + return e.complexity.Todo.ID(childComplexity), true + + case "Todo.parent": + if e.complexity.Todo.Parent == nil { + break + } + + return e.complexity.Todo.Parent(childComplexity), true + + case "Todo.priority": + if e.complexity.Todo.Priority == nil { + break + } + + return e.complexity.Todo.Priority(childComplexity), true + + case "Todo.status": + if e.complexity.Todo.Status == nil { + break + } + + return e.complexity.Todo.Status(childComplexity), true + + case "Todo.text": + if e.complexity.Todo.Text == nil { + break + } + + return e.complexity.Todo.Text(childComplexity), true + + case "TodoConnection.edges": + if e.complexity.TodoConnection.Edges == nil { + break + } + + return e.complexity.TodoConnection.Edges(childComplexity), true + + case "TodoConnection.pageInfo": + if e.complexity.TodoConnection.PageInfo == nil { + break + } + + return e.complexity.TodoConnection.PageInfo(childComplexity), true + + case "TodoConnection.totalCount": + if e.complexity.TodoConnection.TotalCount == nil { + break + } + + return e.complexity.TodoConnection.TotalCount(childComplexity), true + + case "TodoEdge.cursor": + if e.complexity.TodoEdge.Cursor == nil { + break + } + + return e.complexity.TodoEdge.Cursor(childComplexity), true + + case "TodoEdge.node": + if e.complexity.TodoEdge.Node == nil { + break + } + + return e.complexity.TodoEdge.Node(childComplexity), true + + case "User.age": + if e.complexity.User.Age == nil { + break + } + + return e.complexity.User.Age(childComplexity), true + + case "User.amount": + if e.complexity.User.Amount == nil { + break + } + + return e.complexity.User.Amount(childComplexity), true + + case "User.id": + if e.complexity.User.ID == nil { + break + } + + return e.complexity.User.ID(childComplexity), true + + case "User.role": + if e.complexity.User.Role == nil { + break + } + + return e.complexity.User.Role(childComplexity), true + + case "User.username": + if e.complexity.User.Username == nil { + break + } + + return e.complexity.User.Username(childComplexity), true + + } + return 0, false +} + +func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { + rc := graphql.GetOperationContext(ctx) + ec := executionContext{rc, e} + first := true + + switch rc.Operation.Operation { + case ast.Query: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + data := ec._Query(ctx, rc.Operation.SelectionSet) + var buf bytes.Buffer + data.MarshalGQL(&buf) + + return &graphql.Response{ + Data: buf.Bytes(), + } + } + case ast.Mutation: + return func(ctx context.Context) *graphql.Response { + if !first { + return nil + } + first = false + 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 +} + +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 +} + +var sources = []*ast.Source{ + {Name: "todo.graphql", Input: `directive @someDirective(stringArg: String, boolArg: Boolean) on OBJECT + | INPUT_OBJECT + | SCALAR + | FIELD_DEFINITION + +interface Node { + id: ID! +} + +type CategoryConfig { + maxMembers: Int +} + +input CategoryConfigInput { + maxMembers: Int +} + +enum CategoryStatus { + ENABLED + DISABLED +} + +enum Status { + IN_PROGRESS + COMPLETED +} + +scalar Time +scalar Duration +scalar Uint64 + +type Todo implements Node { + id: ID! + createdAt: Time + status: Status! + priority: Int! + text: String! + parent: Todo + children: [Todo!] + category: Category +} + +type Category implements Node { + id: ID! + text: String! + strings: [String] +} + +input TodoInput { + status: Status! = IN_PROGRESS + priority: Int + text: String! + parent: ID + category_id: ID +} + +scalar Cursor + +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: Cursor + endCursor: Cursor +} + +type TodoConnection { + totalCount: Int! + pageInfo: PageInfo! + edges: [TodoEdge] +} + +type TodoEdge { + node: Todo + cursor: Cursor! +} + +enum OrderDirection { + ASC + DESC +} + +enum TodoOrderField { + CREATED_AT + PRIORITY + STATUS + TEXT +} + +input TodoOrder { + direction: OrderDirection! + field: TodoOrderField +} + +enum Role { + ADMIN + USER + UNKNOWN +} + +type User implements Node { + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! +} + +type Query { + node(id: ID!): Node + nodes(ids: [ID!]!): [Node]! + todos(after: Cursor, first: Int, before: Cursor, last: Int, orderBy: TodoOrder): TodoConnection +} + +type Mutation { + createTodo(todo: TodoInput!): Todo! + clearTodos: Int! +} +`, BuiltIn: false}, +} +var parsedSchema = gqlparser.MustLoadSchema(sources...) + +// endregion ************************** generated!.gotpl ************************** + +// region ***************************** args.gotpl ***************************** + +func (ec *executionContext) dir_someDirective_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["stringArg"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("stringArg")) + arg0, err = ec.unmarshalOString2ᚖstring(ctx, tmp) + if err != nil { + return nil, err + } + } + args["stringArg"] = arg0 + var arg1 *bool + if tmp, ok := rawArgs["boolArg"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("boolArg")) + arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["boolArg"] = arg1 + 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{}{} + var arg0 TodoInput + if tmp, ok := rawArgs["todo"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("todo")) + arg0, err = ec.unmarshalNTodoInput2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚐTodoInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["todo"] = 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_Query_node_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 int + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2int(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_nodes_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 []int + if tmp, ok := rawArgs["ids"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ids")) + arg0, err = ec.unmarshalNID2ᚕintᚄ(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ids"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_todos_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *ent.Cursor + if tmp, ok := rawArgs["after"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("after")) + arg0, err = ec.unmarshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, tmp) + if err != nil { + return nil, err + } + } + args["after"] = arg0 + var arg1 *int + if tmp, ok := rawArgs["first"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("first")) + arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["first"] = arg1 + var arg2 *ent.Cursor + if tmp, ok := rawArgs["before"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("before")) + arg2, err = ec.unmarshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, tmp) + if err != nil { + return nil, err + } + } + args["before"] = arg2 + var arg3 *int + if tmp, ok := rawArgs["last"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("last")) + arg3, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["last"] = arg3 + var arg4 *ent.TodoOrder + if tmp, ok := rawArgs["orderBy"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("orderBy")) + arg4, err = ec.unmarshalOTodoOrder2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrder(ctx, tmp) + if err != nil { + return nil, err + } + } + args["orderBy"] = arg4 + return args, nil +} + +func (ec *executionContext) field___Field_args_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.unmarshalOBoolean2ᚖbool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["includeDeprecated"] = 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) _Category_id(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.(int) + fc.Result = res + return ec.marshalNID2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Category_text(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) _Category_strings(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Strings, 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) _CategoryConfig_maxMembers(ctx context.Context, field graphql.CollectedField, obj *schematype.CategoryConfig) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CategoryConfig", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MaxMembers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalOInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createTodo(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createTodo_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateTodo(rctx, args["todo"].(TodoInput)) + }) + 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.(*ent.Todo) + fc.Result = res + return ec.marshalNTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_clearTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().ClearTodos(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.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.HasNextPage, 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) _PageInfo_hasPreviousPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.HasPreviousPage, 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) _PageInfo_startCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.StartCursor, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.Cursor) + fc.Result = res + return ec.marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) +} + +func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EndCursor, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.Cursor) + fc.Result = res + return ec.marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_node_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Node(rctx, args["id"].(int)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(ent.Noder) + fc.Result = res + return ec.marshalONode2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_nodes_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Nodes(rctx, args["ids"].([]int)) + }) + 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.([]ent.Noder) + fc.Result = res + return ec.marshalNNode2ᚕentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_todos_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Todos(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.TodoOrder)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.TodoConnection) + fc.Result = res + return ec.marshalOTodoConnection2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoConnection(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query___type_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectType(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) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return 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) _Todo_id(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.(int) + fc.Result = res + return ec.marshalNID2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(time.Time) + fc.Result = res + return ec.marshalOTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_status(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Status, 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.(todo.Status) + fc.Result = res + return ec.marshalNStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_priority(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Priority, 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.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_text(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) _Todo_parent(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Parent(ctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.Todo) + fc.Result = res + return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Children(ctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*ent.Todo) + fc.Result = res + return ec.marshalOTodo2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Todo().Category(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.Category) + fc.Result = res + return ec.marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx, field.Selections, res) +} + +func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TodoConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.TotalCount, 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.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TodoConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, 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.(ent.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TodoConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Edges, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*ent.TodoEdge) + fc.Result = res + return ec.marshalOTodoEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx, field.Selections, res) +} + +func (ec *executionContext) _TodoEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TodoEdge", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Node, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.Todo) + fc.Result = res + return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) +} + +func (ec *executionContext) _TodoEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "TodoEdge", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Cursor, 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.(ent.Cursor) + fc.Result = res + return ec.marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.(int) + fc.Result = res + return ec.marshalNID2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_username(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Username, 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) _User_age(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.User().Age(rctx, obj) + }) + 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.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_amount(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.User().Amount(rctx, obj) + }) + 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.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) _User_role(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "User", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Role, 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.(role.Role) + fc.Result = res + return ec.marshalNRole2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋroleᚐRole(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Directive_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Directive_locations(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Directive_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Directive_isRepeatable(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Directive", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___EnumValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___EnumValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___EnumValue_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___EnumValue_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.EnumValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__EnumValue", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Field_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Field_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Field_args(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Field_args_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return 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) ___Field_type(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Field_isDeprecated(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Field_deprecationReason(ctx context.Context, field graphql.CollectedField, obj *introspection.Field) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Field", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___InputValue_name(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___InputValue_description(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___InputValue_type(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___InputValue_defaultValue(ctx context.Context, field graphql.CollectedField, obj *introspection.InputValue) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__InputValue", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Schema_types(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Schema_queryType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Schema_mutationType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Schema_subscriptionType(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Schema_directives(ctx context.Context, field graphql.CollectedField, obj *introspection.Schema) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Schema", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Type_kind(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Type_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Type_description(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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.marshalOString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) ___Type_fields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Type_fields_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Fields(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) ___Type_interfaces(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Type_possibleTypes(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Type_enumValues(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field___Type_enumValues_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.EnumValues(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) ___Type_inputFields(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) ___Type_ofType(ctx context.Context, field graphql.CollectedField, obj *introspection.Type) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "__Type", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.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) +} + +// endregion **************************** field.gotpl ***************************** + +// region **************************** input.gotpl ***************************** + +func (ec *executionContext) unmarshalInputCategoryConfigInput(ctx context.Context, obj interface{}) (schematype.CategoryConfig, error) { + var it schematype.CategoryConfig + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "maxMembers": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("maxMembers")) + it.MaxMembers, err = ec.unmarshalOInt2int(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputTodoInput(ctx context.Context, obj interface{}) (TodoInput, error) { + var it TodoInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + if _, present := asMap["status"]; !present { + asMap["status"] = "IN_PROGRESS" + } + + for k, v := range asMap { + switch k { + case "status": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status")) + it.Status, err = ec.unmarshalNStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐStatus(ctx, v) + if err != nil { + return it, err + } + case "priority": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("priority")) + it.Priority, err = ec.unmarshalOInt2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "text": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("text")) + it.Text, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "parent": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("parent")) + it.Parent, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + case "category_id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("category_id")) + it.CategoryID, err = ec.unmarshalOID2ᚖint(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputTodoOrder(ctx context.Context, obj interface{}) (ent.TodoOrder, error) { + var it ent.TodoOrder + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "direction": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) + it.Direction, err = ec.unmarshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐOrderDirection(ctx, v) + if err != nil { + return it, err + } + case "field": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) + it.Field, err = ec.unmarshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +// endregion **************************** input.gotpl ***************************** + +// region ************************** interface.gotpl *************************** + +func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj ent.Noder) graphql.Marshaler { + switch obj := (obj).(type) { + case nil: + return graphql.Null + case *ent.Todo: + if obj == nil { + return graphql.Null + } + return ec._Todo(ctx, sel, obj) + case *ent.Category: + if obj == nil { + return graphql.Null + } + return ec._Category(ctx, sel, obj) + case *ent.User: + if obj == nil { + return graphql.Null + } + return ec._User(ctx, sel, obj) + default: + panic(fmt.Errorf("unexpected type %T", obj)) + } +} + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var categoryImplementors = []string{"Category", "Node"} + +func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, obj *ent.Category) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, categoryImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Category") + case "id": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_id(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "text": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_text(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "strings": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_strings(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var categoryConfigImplementors = []string{"CategoryConfig"} + +func (ec *executionContext) _CategoryConfig(ctx context.Context, sel ast.SelectionSet, obj *schematype.CategoryConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, categoryConfigImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("CategoryConfig") + case "maxMembers": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryConfig_maxMembers(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var mutationImplementors = []string{"Mutation"} + +func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, mutationImplementors) + ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ + Object: "Mutation", + }) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Mutation") + case "createTodo": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_createTodo(ctx, field) + } + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, innerFunc) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "clearTodos": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Mutation_clearTodos(ctx, field) + } + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, innerFunc) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var pageInfoImplementors = []string{"PageInfo"} + +func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *ent.PageInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, pageInfoImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PageInfo") + case "hasNextPage": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._PageInfo_hasNextPage(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "hasPreviousPage": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._PageInfo_hasPreviousPage(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "startCursor": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._PageInfo_startCursor(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "endCursor": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._PageInfo_endCursor(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + 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) + var invalids uint32 + for i, field := range fields { + innerCtx := graphql.WithRootFieldContext(ctx, &graphql.RootFieldContext{ + Object: field.Name, + Field: field, + }) + + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Query") + case "node": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_node(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "nodes": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_nodes(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "todos": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_todos(ctx, field) + return res + } + + rrm := func(ctx context.Context) graphql.Marshaler { + return ec.OperationContext.RootResolverMiddleware(ctx, innerFunc) + } + + out.Concurrently(i, func() graphql.Marshaler { + return rrm(innerCtx) + }) + case "__type": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___type(ctx, field) + } + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, innerFunc) + + case "__schema": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Query___schema(ctx, field) + } + + out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, innerFunc) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var todoImplementors = []string{"Todo", "Node"} + +func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj *ent.Todo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, todoImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Todo") + case "id": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Todo_id(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "createdAt": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Todo_createdAt(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "status": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Todo_status(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "priority": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Todo_priority(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "text": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Todo_text(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "parent": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Todo_parent(ctx, field, obj) + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "children": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Todo_children(ctx, field, obj) + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "category": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Todo_category(ctx, field, obj) + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var todoConnectionImplementors = []string{"TodoConnection"} + +func (ec *executionContext) _TodoConnection(ctx context.Context, sel ast.SelectionSet, obj *ent.TodoConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, todoConnectionImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TodoConnection") + case "totalCount": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._TodoConnection_totalCount(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "pageInfo": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._TodoConnection_pageInfo(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "edges": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._TodoConnection_edges(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var todoEdgeImplementors = []string{"TodoEdge"} + +func (ec *executionContext) _TodoEdge(ctx context.Context, sel ast.SelectionSet, obj *ent.TodoEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, todoEdgeImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TodoEdge") + case "node": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._TodoEdge_node(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "cursor": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._TodoEdge_cursor(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var userImplementors = []string{"User", "Node"} + +func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *ent.User) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, userImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("User") + case "id": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._User_id(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "username": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._User_username(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "age": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._User_age(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "amount": + field := field + + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._User_amount(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "role": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._User_role(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + 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) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Directive") + case "name": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Directive_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Directive_description(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "locations": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Directive_locations(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "args": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Directive_args(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "isRepeatable": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Directive_isRepeatable(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __EnumValueImplementors = []string{"__EnumValue"} + +func (ec *executionContext) ___EnumValue(ctx context.Context, sel ast.SelectionSet, obj *introspection.EnumValue) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __EnumValueImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__EnumValue") + case "name": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___EnumValue_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___EnumValue_description(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "isDeprecated": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___EnumValue_isDeprecated(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "deprecationReason": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___EnumValue_deprecationReason(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + 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) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Field") + case "name": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Field_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Field_description(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "args": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Field_args(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "type": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Field_type(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "isDeprecated": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Field_isDeprecated(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "deprecationReason": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Field_deprecationReason(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + 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) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__InputValue") + case "name": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___InputValue_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "description": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___InputValue_description(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "type": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___InputValue_type(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "defaultValue": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___InputValue_defaultValue(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + 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) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Schema") + case "types": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Schema_types(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "queryType": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Schema_queryType(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "mutationType": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Schema_mutationType(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "subscriptionType": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Schema_subscriptionType(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "directives": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Schema_directives(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var __TypeImplementors = []string{"__Type"} + +func (ec *executionContext) ___Type(ctx context.Context, sel ast.SelectionSet, obj *introspection.Type) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, __TypeImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("__Type") + case "kind": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_kind(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "name": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_name(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "description": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_description(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "fields": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_fields(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "interfaces": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_interfaces(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "possibleTypes": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_possibleTypes(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "enumValues": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_enumValues(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "inputFields": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_inputFields(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "ofType": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec.___Type_ofType(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + 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, "must not be null") + } + } + return res +} + +func (ec *executionContext) unmarshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx context.Context, v interface{}) (ent.Cursor, error) { + var res ent.Cursor + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx context.Context, sel ast.SelectionSet, v ent.Cursor) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { + res, err := graphql.UnmarshalFloatContext(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNFloat2float64(ctx context.Context, sel ast.SelectionSet, v float64) graphql.Marshaler { + res := graphql.MarshalFloatContext(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return graphql.WrapContextMarshaler(ctx, res) +} + +func (ec *executionContext) unmarshalNID2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalIntID(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNID2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalIntID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) unmarshalNID2ᚕintᚄ(ctx context.Context, v interface{}) ([]int, error) { + var vSlice []interface{} + if v != nil { + vSlice = graphql.CoerceList(v) + } + var err error + res := make([]int, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNID2int(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalNID2ᚕintᚄ(ctx context.Context, sel ast.SelectionSet, v []int) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalNID2int(ctx, sel, v[i]) + } + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalInt(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalNNode2ᚕentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx context.Context, sel ast.SelectionSet, v []ent.Noder) 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.marshalONode2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) unmarshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐOrderDirection(ctx context.Context, v interface{}) (ent.OrderDirection, error) { + var res ent.OrderDirection + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐOrderDirection(ctx context.Context, sel ast.SelectionSet, v ent.OrderDirection) graphql.Marshaler { + return v +} + +func (ec *executionContext) marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx context.Context, sel ast.SelectionSet, v ent.PageInfo) graphql.Marshaler { + return ec._PageInfo(ctx, sel, &v) +} + +func (ec *executionContext) unmarshalNRole2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋroleᚐRole(ctx context.Context, v interface{}) (role.Role, error) { + var res role.Role + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNRole2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋroleᚐRole(ctx context.Context, sel ast.SelectionSet, v role.Role) graphql.Marshaler { + return v +} + +func (ec *executionContext) unmarshalNStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐStatus(ctx context.Context, v interface{}) (todo.Status, error) { + var res todo.Status + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐStatus(ctx context.Context, sel ast.SelectionSet, v todo.Status) graphql.Marshaler { + return v +} + +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, "must not be null") + } + } + return res +} + +func (ec *executionContext) marshalNTodo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx context.Context, sel ast.SelectionSet, v ent.Todo) graphql.Marshaler { + return ec._Todo(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx context.Context, sel ast.SelectionSet, v *ent.Todo) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._Todo(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNTodoInput2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚐTodoInput(ctx context.Context, v interface{}) (TodoInput, error) { + res, err := ec.unmarshalInputTodoInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + +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, "must not be null") + } + } + 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, "must not be null") + } + 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, "must not be null") + } + } + 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) marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx context.Context, sel ast.SelectionSet, v *ent.Category) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Category(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx context.Context, v interface{}) (*ent.Cursor, error) { + if v == nil { + return nil, nil + } + var res = new(ent.Cursor) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx context.Context, sel ast.SelectionSet, v *ent.Cursor) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) unmarshalOID2ᚖint(ctx context.Context, v interface{}) (*int, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalIntID(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOID2ᚖint(ctx context.Context, sel ast.SelectionSet, v *int) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalIntID(*v) + return res +} + +func (ec *executionContext) unmarshalOInt2int(ctx context.Context, v interface{}) (int, error) { + res, err := graphql.UnmarshalInt(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOInt2int(ctx context.Context, sel ast.SelectionSet, v int) graphql.Marshaler { + res := graphql.MarshalInt(v) + return res +} + +func (ec *executionContext) unmarshalOInt2ᚖint(ctx context.Context, v interface{}) (*int, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalInt(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.SelectionSet, v *int) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalInt(*v) + return res +} + +func (ec *executionContext) marshalONode2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx context.Context, sel ast.SelectionSet, v ent.Noder) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Node(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { + res, err := graphql.UnmarshalString(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.SelectionSet, v string) graphql.Marshaler { + res := graphql.MarshalString(v) + return res +} + +func (ec *executionContext) unmarshalOString2ᚕstring(ctx context.Context, v interface{}) ([]string, error) { + if v == nil { + return nil, nil + } + 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.unmarshalOString2string(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) marshalOString2ᚕstring(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + for i := range v { + ret[i] = ec.marshalOString2string(ctx, sel, v[i]) + } + + return ret +} + +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) unmarshalOTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { + res, err := graphql.UnmarshalTime(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { + res := graphql.MarshalTime(v) + return res +} + +func (ec *executionContext) marshalOTodo2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoᚄ(ctx context.Context, sel ast.SelectionSet, v []*ent.Todo) 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.marshalNTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐ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) marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx context.Context, sel ast.SelectionSet, v *ent.Todo) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._Todo(ctx, sel, v) +} + +func (ec *executionContext) marshalOTodoConnection2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoConnection(ctx context.Context, sel ast.SelectionSet, v *ent.TodoConnection) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._TodoConnection(ctx, sel, v) +} + +func (ec *executionContext) marshalOTodoEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx context.Context, sel ast.SelectionSet, v []*ent.TodoEdge) 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.marshalOTodoEdge2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) marshalOTodoEdge2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx context.Context, sel ast.SelectionSet, v *ent.TodoEdge) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._TodoEdge(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOTodoOrder2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrder(ctx context.Context, v interface{}) (*ent.TodoOrder, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputTodoOrder(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) unmarshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx context.Context, v interface{}) (*ent.TodoOrderField, error) { + if v == nil { + return nil, nil + } + var res = new(ent.TodoOrderField) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx context.Context, sel ast.SelectionSet, v *ent.TodoOrderField) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) marshalO__EnumValue2ᚕgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐEnumValueᚄ(ctx context.Context, sel ast.SelectionSet, v []introspection.EnumValue) graphql.Marshaler { + if v == nil { + return graphql.Null + } + 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/entgql/internal/todoplugin/gqlgen.yml b/entgql/internal/todoplugin/gqlgen.yml new file mode 100644 index 000000000..d0b892632 --- /dev/null +++ b/entgql/internal/todoplugin/gqlgen.yml @@ -0,0 +1,46 @@ +# Copyright (c) 2004-present Facebook All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +schema: + - todo.graphql + +resolver: + package: todoplugin + layout: follow-schema + dir: . + +autobind: + - entgo.io/contrib/entgql/internal/todoplugin/ent + # Auto-bind the generated `Status` enum to GraphQL. + - entgo.io/contrib/entgql/internal/todoplugin/ent/todo + +models: + ID: + model: + - github.com/99designs/gqlgen/graphql.IntID + Uint64: + model: + - github.com/99designs/gqlgen/graphql.Uint64 + Duration: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/durationgql.Duration + Node: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent.Noder + # Custom mapping from GraphQL `CategoryStatus` + # to the generated `category.Status` enum type. + CategoryStatus: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status + Role: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role + # Custom mapping from GraphQL `CategoryConfig` and + # `CategoryConfigInput` to `schematype.CategoryConfig`. + CategoryConfig: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig + CategoryConfigInput: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig diff --git a/entgql/internal/todoplugin/models_gen.go b/entgql/internal/todoplugin/models_gen.go new file mode 100644 index 000000000..e3787d581 --- /dev/null +++ b/entgql/internal/todoplugin/models_gen.go @@ -0,0 +1,15 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package todoplugin + +import ( + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" +) + +type TodoInput struct { + Status todo.Status `json:"status"` + Priority *int `json:"priority"` + Text string `json:"text"` + Parent *int `json:"parent"` + CategoryID *int `json:"category_id"` +} diff --git a/entgql/internal/todoplugin/resolver.go b/entgql/internal/todoplugin/resolver.go new file mode 100644 index 000000000..e8f49a854 --- /dev/null +++ b/entgql/internal/todoplugin/resolver.go @@ -0,0 +1,37 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package todoplugin + +import ( + "context" + + "entgo.io/contrib/entgql/internal/todoplugin/ent" + "github.com/99designs/gqlgen/graphql" +) + +// Resolver is the resolver root. +type Resolver struct{ client *ent.Client } + +// NewSchema creates a graphql executable schema. +func NewSchema(client *ent.Client) graphql.ExecutableSchema { + return NewExecutableSchema(Config{ + Resolvers: &Resolver{client}, + Directives: DirectiveRoot{ + SomeDirective: func(ctx context.Context, obj interface{}, next graphql.Resolver, stringArg *string, boolArg *bool) (res interface{}, err error) { + return next(ctx) + }, + }, + }) +} diff --git a/entgql/internal/todoplugin/server/server.go b/entgql/internal/todoplugin/server/server.go new file mode 100644 index 000000000..b1ba58564 --- /dev/null +++ b/entgql/internal/todoplugin/server/server.go @@ -0,0 +1,71 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package main + +import ( + "context" + "net/http" + + "entgo.io/contrib/entgql" + "entgo.io/contrib/entgql/internal/todo" + "entgo.io/contrib/entgql/internal/todo/ent" + "entgo.io/contrib/entgql/internal/todo/ent/migrate" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/handler/debug" + "github.com/99designs/gqlgen/graphql/playground" + "github.com/alecthomas/kong" + "go.uber.org/zap" + + _ "entgo.io/contrib/entgql/internal/todo/ent/runtime" + _ "github.com/mattn/go-sqlite3" +) + +func main() { + var cli struct { + Addr string `name:"address" default:":8081" help:"Address to listen on."` + Debug bool `name:"debug" help:"Enable debugging mode."` + } + kong.Parse(&cli) + + log, _ := zap.NewDevelopment() + client, err := ent.Open( + "sqlite3", + "file:ent?mode=memory&cache=shared&_fk=1", + ) + if err != nil { + log.Fatal("opening ent client", zap.Error(err)) + } + if err := client.Schema.Create( + context.Background(), + migrate.WithGlobalUniqueID(true), + ); err != nil { + log.Fatal("running schema migration", zap.Error(err)) + } + + srv := handler.NewDefaultServer(todo.NewSchema(client)) + srv.Use(entgql.Transactioner{TxOpener: client}) + if cli.Debug { + srv.Use(&debug.Tracer{}) + } + + http.Handle("/", + playground.Handler("Todo", "/query"), + ) + http.Handle("/query", srv) + + log.Info("listening on", zap.String("address", cli.Addr)) + if err := http.ListenAndServe(cli.Addr, nil); err != nil { + log.Error("http server terminated", zap.Error(err)) + } +} diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql new file mode 100644 index 000000000..993be2ccb --- /dev/null +++ b/entgql/internal/todoplugin/todo.graphql @@ -0,0 +1,117 @@ +directive @someDirective(stringArg: String, boolArg: Boolean) on OBJECT + | INPUT_OBJECT + | SCALAR + | FIELD_DEFINITION + +interface Node { + id: ID! +} + +type CategoryConfig { + maxMembers: Int +} + +input CategoryConfigInput { + maxMembers: Int +} + +enum CategoryStatus { + ENABLED + DISABLED +} + +enum Status { + IN_PROGRESS + COMPLETED +} + +scalar Time +scalar Duration +scalar Uint64 + +type Todo implements Node { + id: ID! + createdAt: Time + status: Status! + priority: Int! + text: String! + parent: Todo + children: [Todo!] + category: Category +} + +type Category implements Node { + id: ID! + text: String! + strings: [String] +} + +input TodoInput { + status: Status! = IN_PROGRESS + priority: Int + text: String! + parent: ID + category_id: ID +} + +scalar Cursor + +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: Cursor + endCursor: Cursor +} + +type TodoConnection { + totalCount: Int! + pageInfo: PageInfo! + edges: [TodoEdge] +} + +type TodoEdge { + node: Todo + cursor: Cursor! +} + +enum OrderDirection { + ASC + DESC +} + +enum TodoOrderField { + CREATED_AT + PRIORITY + STATUS + TEXT +} + +input TodoOrder { + direction: OrderDirection! + field: TodoOrderField +} + +enum Role { + ADMIN + USER + UNKNOWN +} + +type User implements Node { + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! +} + +type Query { + node(id: ID!): Node + nodes(ids: [ID!]!): [Node]! + todos(after: Cursor, first: Int, before: Cursor, last: Int, orderBy: TodoOrder): TodoConnection +} + +type Mutation { + createTodo(todo: TodoInput!): Todo! + clearTodos: Int! +} diff --git a/entgql/internal/todoplugin/todo.resolvers.go b/entgql/internal/todoplugin/todo.resolvers.go new file mode 100644 index 000000000..39837efa7 --- /dev/null +++ b/entgql/internal/todoplugin/todo.resolvers.go @@ -0,0 +1,87 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package todoplugin + +// 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. + +import ( + "context" + "fmt" + + "entgo.io/contrib/entgql/internal/todoplugin/ent" +) + +func (r *mutationResolver) CreateTodo(ctx context.Context, todo TodoInput) (*ent.Todo, error) { + client := ent.FromContext(ctx) + return client.Todo. + Create(). + SetStatus(todo.Status). + SetNillablePriority(todo.Priority). + SetText(todo.Text). + SetNillableParentID(todo.Parent). + Save(ctx) +} + +func (r *mutationResolver) ClearTodos(ctx context.Context) (int, error) { + client := ent.FromContext(ctx) + return client.Todo. + Delete(). + Exec(ctx) +} + +func (r *queryResolver) Node(ctx context.Context, id int) (ent.Noder, error) { + return r.client.Noder(ctx, id) +} + +func (r *queryResolver) Nodes(ctx context.Context, ids []int) ([]ent.Noder, error) { + return r.client.Noders(ctx, ids) +} + +func (r *queryResolver) Todos(ctx context.Context, after *ent.Cursor, first *int, before *ent.Cursor, last *int, orderBy *ent.TodoOrder) (*ent.TodoConnection, error) { + return r.client.Todo.Query(). + Paginate(ctx, after, first, before, last, + ent.WithTodoOrder(orderBy), + ) +} + +func (r *todoResolver) Category(ctx context.Context, obj *ent.Todo) (*ent.Category, error) { + panic(fmt.Errorf("not implemented")) +} + +func (r *userResolver) Age(ctx context.Context, obj *ent.User) (float64, error) { + return float64(obj.Age), nil +} + +func (r *userResolver) Amount(ctx context.Context, obj *ent.User) (float64, error) { + return float64(obj.Amount), 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} } + +// Todo returns TodoResolver implementation. +func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } + +// User returns UserResolver implementation. +func (r *Resolver) User() UserResolver { return &userResolver{r} } + +type mutationResolver struct{ *Resolver } +type queryResolver struct{ *Resolver } +type todoResolver struct{ *Resolver } +type userResolver struct{ *Resolver } diff --git a/entgql/internal/todoplugin/todo_test.go b/entgql/internal/todoplugin/todo_test.go new file mode 100644 index 000000000..c968836c8 --- /dev/null +++ b/entgql/internal/todoplugin/todo_test.go @@ -0,0 +1,803 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package todoplugin_test + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "sort" + "strconv" + "strings" + "testing" + "time" + + "entgo.io/contrib/entgql" + gen "entgo.io/contrib/entgql/internal/todoplugin" + "entgo.io/contrib/entgql/internal/todoplugin/ent" + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/enttest" + "entgo.io/contrib/entgql/internal/todoplugin/ent/migrate" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/ent/dialect" + "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/AlekSi/pointer" + "github.com/stretchr/testify/suite" + "github.com/vektah/gqlparser/v2/gqlerror" + + _ "github.com/mattn/go-sqlite3" +) + +type todoTestSuite struct { + suite.Suite + *client.Client + ent *ent.Client +} + +const ( + queryAll = `query { + todos { + totalCount + edges { + node { + id + status + } + cursor + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + }` + maxTodos = 32 + idOffset = 1 << 32 +) + +func (s *todoTestSuite) SetupTest() { + s.ent = enttest.Open(s.T(), dialect.SQLite, + fmt.Sprintf("file:%s-%d?mode=memory&cache=shared&_fk=1", + s.T().Name(), time.Now().UnixNano(), + ), + enttest.WithMigrateOptions(migrate.WithGlobalUniqueID(true)), + ) + + srv := handler.NewDefaultServer(gen.NewSchema(s.ent)) + srv.AddTransport(transport.POST{}) + srv.Use(entgql.Transactioner{TxOpener: s.ent}) + s.Client = client.New(srv) + + const mutation = `mutation($priority: Int, $text: String!, $parent: ID) { + createTodo(todo: {status: COMPLETED, priority: $priority, text: $text, parent: $parent}) { + id + } + }` + var ( + rsp struct { + CreateTodo struct { + ID string + } + } + root = idOffset + 1 + ) + for i := 1; i <= maxTodos; i++ { + id := strconv.Itoa(idOffset + i) + var parent *int + if i != 1 { + if i%2 != 0 { + parent = pointer.ToInt(idOffset + i - 2) + } else { + parent = pointer.ToInt(root) + } + } + err := s.Post(mutation, &rsp, + client.Var("priority", i), + client.Var("text", id), + client.Var("parent", parent), + ) + s.Require().NoError(err) + s.Require().Equal(id, rsp.CreateTodo.ID) + } +} + +func TestTodo(t *testing.T) { + suite.Run(t, &todoTestSuite{}) +} + +type response struct { + Todos struct { + TotalCount int + Edges []struct { + Node struct { + ID string + CreatedAt string + Priority int + Status todo.Status + Text string + Parent struct { + ID string + } + } + Cursor string + } + PageInfo struct { + HasNextPage bool + HasPreviousPage bool + StartCursor *string + EndCursor *string + } + } +} + +func (s *todoTestSuite) TestQueryEmpty() { + { + var rsp struct{ ClearTodos int } + err := s.Post(`mutation { clearTodos }`, &rsp) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.ClearTodos) + } + var rsp response + err := s.Post(queryAll, &rsp) + s.Require().NoError(err) + s.Require().Zero(rsp.Todos.TotalCount) + s.Require().Empty(rsp.Todos.Edges) + s.Require().False(rsp.Todos.PageInfo.HasNextPage) + s.Require().False(rsp.Todos.PageInfo.HasPreviousPage) + s.Require().Nil(rsp.Todos.PageInfo.StartCursor) + s.Require().Nil(rsp.Todos.PageInfo.EndCursor) +} + +func (s *todoTestSuite) TestQueryAll() { + var rsp response + err := s.Post(queryAll, &rsp) + s.Require().NoError(err) + + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().Len(rsp.Todos.Edges, maxTodos) + s.Require().False(rsp.Todos.PageInfo.HasNextPage) + s.Require().False(rsp.Todos.PageInfo.HasPreviousPage) + s.Require().Equal( + rsp.Todos.Edges[0].Cursor, + *rsp.Todos.PageInfo.StartCursor, + ) + s.Require().Equal( + rsp.Todos.Edges[len(rsp.Todos.Edges)-1].Cursor, + *rsp.Todos.PageInfo.EndCursor, + ) + for i, edge := range rsp.Todos.Edges { + s.Require().Equal(strconv.Itoa(idOffset+i+1), edge.Node.ID) + s.Require().EqualValues(todo.StatusCompleted, edge.Node.Status) + s.Require().NotEmpty(edge.Cursor) + } +} + +func (s *todoTestSuite) TestPageForward() { + const ( + query = `query($after: Cursor, $first: Int) { + todos(after: $after, first: $first) { + totalCount + edges { + node { + id + } + cursor + } + pageInfo { + hasNextPage + endCursor + } + } + }` + first = 5 + ) + var ( + after interface{} + rsp response + id = idOffset + 1 + ) + for i := 0; i < maxTodos/first; i++ { + err := s.Post(query, &rsp, + client.Var("after", after), + client.Var("first", first), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().Len(rsp.Todos.Edges, first) + s.Require().True(rsp.Todos.PageInfo.HasNextPage) + s.Require().NotEmpty(rsp.Todos.PageInfo.EndCursor) + + for _, edge := range rsp.Todos.Edges { + s.Require().Equal(strconv.Itoa(id), edge.Node.ID) + s.Require().NotEmpty(edge.Cursor) + id++ + } + after = rsp.Todos.PageInfo.EndCursor + } + + err := s.Post(query, &rsp, + client.Var("after", rsp.Todos.PageInfo.EndCursor), + client.Var("first", first), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().NotEmpty(rsp.Todos.Edges) + s.Require().Len(rsp.Todos.Edges, maxTodos%first) + s.Require().False(rsp.Todos.PageInfo.HasNextPage) + s.Require().NotEmpty(rsp.Todos.PageInfo.EndCursor) + + for _, edge := range rsp.Todos.Edges { + s.Require().Equal(strconv.Itoa(id), edge.Node.ID) + s.Require().NotEmpty(edge.Cursor) + id++ + } + + after = rsp.Todos.PageInfo.EndCursor + rsp = response{} + err = s.Post(query, &rsp, + client.Var("after", after), + client.Var("first", first), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().Empty(rsp.Todos.Edges) + s.Require().Empty(rsp.Todos.PageInfo.EndCursor) + s.Require().False(rsp.Todos.PageInfo.HasNextPage) +} + +func (s *todoTestSuite) TestPageBackwards() { + const ( + query = `query($before: Cursor, $last: Int) { + todos(before: $before, last: $last) { + totalCount + edges { + node { + id + } + cursor + } + pageInfo { + hasPreviousPage + startCursor + } + } + }` + last = 7 + ) + var ( + before interface{} + rsp response + id = idOffset + maxTodos + ) + for i := 0; i < maxTodos/last; i++ { + err := s.Post(query, &rsp, + client.Var("before", before), + client.Var("last", last), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().Len(rsp.Todos.Edges, last) + s.Require().True(rsp.Todos.PageInfo.HasPreviousPage) + s.Require().NotEmpty(rsp.Todos.PageInfo.StartCursor) + + for i := len(rsp.Todos.Edges) - 1; i >= 0; i-- { + edge := &rsp.Todos.Edges[i] + s.Require().Equal(strconv.Itoa(id), edge.Node.ID) + s.Require().NotEmpty(edge.Cursor) + id-- + } + before = rsp.Todos.PageInfo.StartCursor + } + + err := s.Post(query, &rsp, + client.Var("before", rsp.Todos.PageInfo.StartCursor), + client.Var("last", last), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().NotEmpty(rsp.Todos.Edges) + s.Require().Len(rsp.Todos.Edges, maxTodos%last) + s.Require().False(rsp.Todos.PageInfo.HasPreviousPage) + s.Require().NotEmpty(rsp.Todos.PageInfo.StartCursor) + + for i := len(rsp.Todos.Edges) - 1; i >= 0; i-- { + edge := &rsp.Todos.Edges[i] + s.Require().Equal(strconv.Itoa(id), edge.Node.ID) + s.Require().NotEmpty(edge.Cursor) + id-- + } + s.Require().Equal(idOffset, id) + + before = rsp.Todos.PageInfo.StartCursor + rsp = response{} + err = s.Post(query, &rsp, + client.Var("before", before), + client.Var("last", last), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + s.Require().Empty(rsp.Todos.Edges) + s.Require().Empty(rsp.Todos.PageInfo.StartCursor) + s.Require().False(rsp.Todos.PageInfo.HasPreviousPage) +} + +func (s *todoTestSuite) TestPaginationOrder() { + const ( + query = `query($after: Cursor, $first: Int, $before: Cursor, $last: Int, $direction: OrderDirection!, $field: TodoOrderField!) { + todos(after: $after, first: $first, before: $before, last: $last, orderBy: { direction: $direction, field: $field }) { + totalCount + edges { + node { + id + createdAt + priority + status + text + } + cursor + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + }` + step = 5 + steps = maxTodos/step + 1 + ) + s.Run("ForwardAscending", func() { + var ( + rsp response + endText string + ) + for i := 0; i < steps; i++ { + err := s.Post(query, &rsp, + client.Var("after", rsp.Todos.PageInfo.EndCursor), + client.Var("first", step), + client.Var("direction", "ASC"), + client.Var("field", "TEXT"), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + if i < steps-1 { + s.Require().Len(rsp.Todos.Edges, step) + s.Require().True(rsp.Todos.PageInfo.HasNextPage) + } else { + s.Require().Len(rsp.Todos.Edges, maxTodos%step) + s.Require().False(rsp.Todos.PageInfo.HasNextPage) + } + s.Require().True(sort.SliceIsSorted(rsp.Todos.Edges, func(i, j int) bool { + return rsp.Todos.Edges[i].Node.Text < rsp.Todos.Edges[j].Node.Text + })) + s.Require().NotNil(rsp.Todos.PageInfo.StartCursor) + s.Require().Equal(*rsp.Todos.PageInfo.StartCursor, rsp.Todos.Edges[0].Cursor) + s.Require().NotNil(rsp.Todos.PageInfo.EndCursor) + end := rsp.Todos.Edges[len(rsp.Todos.Edges)-1] + s.Require().Equal(*rsp.Todos.PageInfo.EndCursor, end.Cursor) + if i > 0 { + s.Require().Less(endText, rsp.Todos.Edges[0].Node.Text) + } + endText = end.Node.Text + } + }) + s.Run("ForwardDescending", func() { + var ( + rsp response + endID int + ) + for i := 0; i < steps; i++ { + err := s.Post(query, &rsp, + client.Var("after", rsp.Todos.PageInfo.EndCursor), + client.Var("first", step), + client.Var("direction", "DESC"), + client.Var("field", "TEXT"), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + if i < steps-1 { + s.Require().Len(rsp.Todos.Edges, step) + s.Require().True(rsp.Todos.PageInfo.HasNextPage) + } else { + s.Require().Len(rsp.Todos.Edges, maxTodos%step) + s.Require().False(rsp.Todos.PageInfo.HasNextPage) + } + s.Require().True(sort.SliceIsSorted(rsp.Todos.Edges, func(i, j int) bool { + left, _ := strconv.Atoi(rsp.Todos.Edges[i].Node.ID) + right, _ := strconv.Atoi(rsp.Todos.Edges[j].Node.ID) + return left > right + })) + s.Require().NotNil(rsp.Todos.PageInfo.StartCursor) + s.Require().Equal(*rsp.Todos.PageInfo.StartCursor, rsp.Todos.Edges[0].Cursor) + s.Require().NotNil(rsp.Todos.PageInfo.EndCursor) + end := rsp.Todos.Edges[len(rsp.Todos.Edges)-1] + s.Require().Equal(*rsp.Todos.PageInfo.EndCursor, end.Cursor) + if i > 0 { + id, _ := strconv.Atoi(rsp.Todos.Edges[0].Node.ID) + s.Require().Greater(endID, id) + } + endID, _ = strconv.Atoi(end.Node.ID) + } + }) + s.Run("BackwardAscending", func() { + var ( + rsp response + startPriority int + ) + for i := 0; i < steps; i++ { + err := s.Post(query, &rsp, + client.Var("before", rsp.Todos.PageInfo.StartCursor), + client.Var("last", step), + client.Var("direction", "ASC"), + client.Var("field", "PRIORITY"), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + if i < steps-1 { + s.Require().Len(rsp.Todos.Edges, step) + s.Require().True(rsp.Todos.PageInfo.HasPreviousPage) + } else { + s.Require().Len(rsp.Todos.Edges, maxTodos%step) + s.Require().False(rsp.Todos.PageInfo.HasPreviousPage) + } + s.Require().True(sort.SliceIsSorted(rsp.Todos.Edges, func(i, j int) bool { + return rsp.Todos.Edges[i].Node.Priority < rsp.Todos.Edges[j].Node.Priority + })) + s.Require().NotNil(rsp.Todos.PageInfo.StartCursor) + start := rsp.Todos.Edges[0] + s.Require().Equal(*rsp.Todos.PageInfo.StartCursor, start.Cursor) + s.Require().NotNil(rsp.Todos.PageInfo.EndCursor) + end := rsp.Todos.Edges[len(rsp.Todos.Edges)-1] + s.Require().Equal(*rsp.Todos.PageInfo.EndCursor, end.Cursor) + if i > 0 { + s.Require().Greater(startPriority, end.Node.Priority) + } + startPriority = start.Node.Priority + } + }) + s.Run("BackwardDescending", func() { + var ( + rsp response + startCreatedAt time.Time + ) + for i := 0; i < steps; i++ { + err := s.Post(query, &rsp, + client.Var("before", rsp.Todos.PageInfo.StartCursor), + client.Var("last", step), + client.Var("direction", "DESC"), + client.Var("field", "CREATED_AT"), + ) + s.Require().NoError(err) + s.Require().Equal(maxTodos, rsp.Todos.TotalCount) + if i < steps-1 { + s.Require().Len(rsp.Todos.Edges, step) + s.Require().True(rsp.Todos.PageInfo.HasPreviousPage) + } else { + s.Require().Len(rsp.Todos.Edges, maxTodos%step) + s.Require().False(rsp.Todos.PageInfo.HasPreviousPage) + } + s.Require().True(sort.SliceIsSorted(rsp.Todos.Edges, func(i, j int) bool { + left, _ := time.Parse(time.RFC3339, rsp.Todos.Edges[i].Node.CreatedAt) + right, _ := time.Parse(time.RFC3339, rsp.Todos.Edges[j].Node.CreatedAt) + return left.After(right) + })) + s.Require().NotNil(rsp.Todos.PageInfo.StartCursor) + start := rsp.Todos.Edges[0] + s.Require().Equal(*rsp.Todos.PageInfo.StartCursor, start.Cursor) + s.Require().NotNil(rsp.Todos.PageInfo.EndCursor) + end := rsp.Todos.Edges[len(rsp.Todos.Edges)-1] + s.Require().Equal(*rsp.Todos.PageInfo.EndCursor, end.Cursor) + if i > 0 { + endCreatedAt, _ := time.Parse(time.RFC3339, end.Node.CreatedAt) + s.Require().True(startCreatedAt.Before(endCreatedAt) || startCreatedAt.Equal(endCreatedAt)) + } + startCreatedAt, _ = time.Parse(time.RFC3339, start.Node.CreatedAt) + } + }) +} + +func (s *todoTestSuite) TestNode() { + const ( + query = `query($id: ID!) { + todo: node(id: $id) { + ... on Todo { + priority + } + } + }` + ) + var rsp struct{ Todo struct{ Priority int } } + err := s.Post(query, &rsp, client.Var("id", idOffset+maxTodos)) + s.Require().NoError(err) + err = s.Post(query, &rsp, client.Var("id", -1)) + var jerr client.RawJsonError + s.Require().True(errors.As(err, &jerr)) + var errs gqlerror.List + err = json.Unmarshal(jerr.RawMessage, &errs) + s.Require().NoError(err) + s.Require().Len(errs, 1) + s.Require().Equal("Could not resolve to a node with the global id of '-1'", errs[0].Message) + s.Require().Equal("NOT_FOUND", errs[0].Extensions["code"]) +} + +func (s *todoTestSuite) TestNodes() { + const ( + query = `query($ids: [ID!]!) { + todos: nodes(ids: $ids) { + ... on Todo { + text + } + } + }` + ) + var rsp struct{ Todos []*struct{ Text string } } + ids := []int{1, 2, 3, 3, 3, maxTodos + 1, 2, 2, maxTodos + 5} + for i := range ids { + ids[i] = idOffset + ids[i] + } + err := s.Post(query, &rsp, client.Var("ids", ids)) + s.Require().Error(err) + s.Require().Len(rsp.Todos, len(ids)) + errmsgs := make([]string, 0, 2) + for i, id := range ids { + if id <= idOffset+maxTodos { + s.Require().Equal(strconv.Itoa(id), rsp.Todos[i].Text) + } else { + s.Require().Nil(rsp.Todos[i]) + errmsgs = append(errmsgs, + fmt.Sprintf("Could not resolve to a node with the global id of '%d'", id), + ) + } + } + + var jerr client.RawJsonError + s.Require().True(errors.As(err, &jerr)) + var errs gqlerror.List + err = json.Unmarshal(jerr.RawMessage, &errs) + s.Require().NoError(err) + s.Require().Len(errs, len(errmsgs)) + for i, err := range errs { + s.Require().Equal(errmsgs[i], err.Message) + s.Require().Equal("NOT_FOUND", err.Extensions["code"]) + } +} + +func (s *todoTestSuite) TestNodeCollection() { + const ( + query = `query($id: ID!) { + todo: node(id: $id) { + ... on Todo { + parent { + text + parent { + text + } + } + children { + text + children { + text + } + } + } + } + }` + ) + var rsp struct { + Todo struct { + Parent *struct { + Text string + Parent *struct { + Text string + } + } + Children []struct { + Text string + Children []struct { + Text string + } + } + } + } + err := s.Post(query, &rsp, client.Var("id", idOffset+1)) + s.Require().NoError(err) + s.Require().Nil(rsp.Todo.Parent) + s.Require().Len(rsp.Todo.Children, maxTodos/2+1) + s.Require().Condition(func() bool { + for _, child := range rsp.Todo.Children { + if child.Text == strconv.Itoa(idOffset+3) { + s.Require().Len(child.Children, 1) + s.Require().Equal(strconv.Itoa(idOffset+5), child.Children[0].Text) + return true + } + } + return false + }) + + err = s.Post(query, &rsp, client.Var("id", idOffset+4)) + s.Require().NoError(err) + s.Require().NotNil(rsp.Todo.Parent) + s.Require().Equal(strconv.Itoa(idOffset+1), rsp.Todo.Parent.Text) + s.Require().Empty(rsp.Todo.Children) + + err = s.Post(query, &rsp, client.Var("id", strconv.Itoa(idOffset+5))) + s.Require().NoError(err) + s.Require().NotNil(rsp.Todo.Parent) + s.Require().Equal(strconv.Itoa(idOffset+3), rsp.Todo.Parent.Text) + s.Require().NotNil(rsp.Todo.Parent.Parent) + s.Require().Equal(strconv.Itoa(idOffset+1), rsp.Todo.Parent.Parent.Text) + s.Require().Len(rsp.Todo.Children, 1) + s.Require().Equal(strconv.Itoa(idOffset+7), rsp.Todo.Children[0].Text) +} + +func (s *todoTestSuite) TestConnCollection() { + const ( + query = `query { + todos { + edges { + node { + id + parent { + id + } + children { + id + } + } + } + } + }` + ) + var rsp struct { + Todos struct { + Edges []struct { + Node struct { + ID string + Parent *struct { + ID string + } + Children []struct { + ID string + } + } + } + } + } + + err := s.Post(query, &rsp) + s.Require().NoError(err) + s.Require().Len(rsp.Todos.Edges, maxTodos) + + for i, edge := range rsp.Todos.Edges { + switch { + case i == 0: + s.Require().Nil(edge.Node.Parent) + s.Require().Len(edge.Node.Children, maxTodos/2+1) + case i%2 == 0: + s.Require().NotNil(edge.Node.Parent) + id, err := strconv.Atoi(edge.Node.Parent.ID) + s.Require().NoError(err) + s.Require().Equal(idOffset+i-1, id) + if i < len(rsp.Todos.Edges)-2 { + s.Require().Len(edge.Node.Children, 1) + } else { + s.Require().Empty(edge.Node.Children) + } + case i%2 != 0: + s.Require().NotNil(edge.Node.Parent) + s.Require().Equal(strconv.Itoa(idOffset+1), edge.Node.Parent.ID) + s.Require().Empty(edge.Node.Children) + } + } +} + +func (s *todoTestSuite) TestEnumEncoding() { + s.Run("Encode", func() { + const status = todo.StatusCompleted + s.Require().Implements((*graphql.Marshaler)(nil), status) + var b strings.Builder + status.MarshalGQL(&b) + str := b.String() + const quote = `"` + s.Require().Equal(quote, str[:1]) + s.Require().Equal(quote, str[len(str)-1:]) + str = str[1 : len(str)-1] + s.Require().EqualValues(status, str) + }) + s.Run("Decode", func() { + const want = todo.StatusInProgress + var got todo.Status + s.Require().Implements((*graphql.Unmarshaler)(nil), &got) + err := got.UnmarshalGQL(want.String()) + s.Require().NoError(err) + s.Require().Equal(want, got) + }) +} + +func (s *todoTestSuite) TestNodeOptions() { + ctx := context.Background() + td := s.ent.Todo.Create().SetText("text").SetStatus(todo.StatusInProgress).SaveX(ctx) + + nr, err := s.ent.Noder(ctx, td.ID) + s.Require().NoError(err) + s.Require().IsType(nr, (*ent.Todo)(nil)) + s.Require().Equal(td.ID, nr.(*ent.Todo).ID) + + nr, err = s.ent.Noder(ctx, td.ID, ent.WithFixedNodeType(todo.Table)) + s.Require().NoError(err) + s.Require().IsType(nr, (*ent.Todo)(nil)) + s.Require().Equal(td.ID, nr.(*ent.Todo).ID) + + _, err = s.ent.Noder(ctx, td.ID, ent.WithNodeType(func(context.Context, int) (string, error) { + return "", errors.New("bad node type") + })) + s.Require().EqualError(err, "bad node type") +} + +func (s *todoTestSuite) TestMutationFieldCollection() { + var rsp struct { + CreateTodo struct { + Text string + Parent struct { + ID string + Text string + } + } + } + err := s.Post(`mutation { + createTodo(todo: { text: "OKE", parent: 4294967297 }) { + parent { + id + text + } + text + } + }`, &rsp, client.Var("text", s.T().Name())) + s.Require().NoError(err) + s.Require().Equal("OKE", rsp.CreateTodo.Text) + s.Require().Equal(strconv.Itoa(idOffset+1), rsp.CreateTodo.Parent.ID) + s.Require().Equal(strconv.Itoa(idOffset+1), rsp.CreateTodo.Parent.Text) +} + +func (s *todoTestSuite) TestQueryJSONFields() { + var ( + ctx = context.Background() + cat = s.ent.Category.Create().SetText("Disabled").SetStatus(category.StatusDisabled).SetStrings([]string{"a", "b"}).SetText("category").SaveX(ctx) + rsp struct { + Node struct { + Text string + Strings []string + } + } + ) + err := s.Post(`query node($id: ID!) { + node(id: $id) { + ... on Category { + text + strings + } + } + }`, &rsp, client.Var("id", cat.ID)) + s.Require().NoError(err) + s.Require().Equal(cat.Text, rsp.Node.Text) + s.Require().Equal(cat.Strings, rsp.Node.Strings) +} From 285ac17ba45cec72339a65eeb6e70845964311a8 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 21:16:57 +0000 Subject: [PATCH 04/23] chore: update todoplugin example --- entgql/internal/todoplugin/ent/category.go | 31 +- .../todoplugin/ent/category/category.go | 6 +- .../internal/todoplugin/ent/category/where.go | 112 +++++- .../todoplugin/ent/category_create.go | 29 +- .../todoplugin/ent/category_update.go | 101 ++--- entgql/internal/todoplugin/ent/gql_node.go | 24 +- .../internal/todoplugin/ent/migrate/schema.go | 2 +- entgql/internal/todoplugin/ent/mutation.go | 147 +++---- .../todoplugin/ent/schema/category.go | 13 +- .../todoplugin/ent/schema/uuidgql/uuidgql.go | 38 ++ entgql/internal/todoplugin/generated.go | 378 +++++++++++++++--- entgql/internal/todoplugin/gqlgen.yml | 3 + entgql/internal/todoplugin/todo.graphql | 40 +- entgql/internal/todoplugin/todo_test.go | 5 +- 14 files changed, 666 insertions(+), 263 deletions(-) create mode 100644 entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go diff --git a/entgql/internal/todoplugin/ent/category.go b/entgql/internal/todoplugin/ent/category.go index a6d67ffb3..e52f533b2 100644 --- a/entgql/internal/todoplugin/ent/category.go +++ b/entgql/internal/todoplugin/ent/category.go @@ -17,7 +17,6 @@ package ent import ( - "encoding/json" "fmt" "strings" "time" @@ -25,6 +24,7 @@ import ( "entgo.io/contrib/entgql/internal/todoplugin/ent/category" "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/ent/dialect/sql" + "github.com/google/uuid" ) // Category is the model entity for the Category schema. @@ -34,6 +34,8 @@ type Category struct { ID int `json:"id,omitempty"` // Text holds the value of the "text" field. Text string `json:"text,omitempty"` + // UUIDA holds the value of the "uuid_a" field. + UUIDA *uuid.UUID `json:"uuid_a,omitempty"` // Status holds the value of the "status" field. Status category.Status `json:"status,omitempty"` // Config holds the value of the "config" field. @@ -42,8 +44,6 @@ type Category struct { Duration time.Duration `json:"duration,omitempty"` // Count holds the value of the "count" field. Count uint64 `json:"count,omitempty"` - // Strings holds the value of the "strings" field. - Strings []string `json:"strings,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the CategoryQuery when eager-loading is set. Edges CategoryEdges `json:"edges"` @@ -72,8 +72,8 @@ func (*Category) scanValues(columns []string) ([]interface{}, error) { values := make([]interface{}, len(columns)) for i := range columns { switch columns[i] { - case category.FieldStrings: - values[i] = new([]byte) + case category.FieldUUIDA: + values[i] = &sql.NullScanner{S: new(uuid.UUID)} case category.FieldConfig: values[i] = new(schematype.CategoryConfig) case category.FieldID, category.FieldDuration, category.FieldCount: @@ -107,6 +107,13 @@ func (c *Category) assignValues(columns []string, values []interface{}) error { } else if value.Valid { c.Text = value.String } + case category.FieldUUIDA: + if value, ok := values[i].(*sql.NullScanner); !ok { + return fmt.Errorf("unexpected type %T for field uuid_a", values[i]) + } else if value.Valid { + c.UUIDA = new(uuid.UUID) + *c.UUIDA = *value.S.(*uuid.UUID) + } case category.FieldStatus: if value, ok := values[i].(*sql.NullString); !ok { return fmt.Errorf("unexpected type %T for field status", values[i]) @@ -131,14 +138,6 @@ func (c *Category) assignValues(columns []string, values []interface{}) error { } else if value.Valid { c.Count = uint64(value.Int64) } - case category.FieldStrings: - if value, ok := values[i].(*[]byte); !ok { - return fmt.Errorf("unexpected type %T for field strings", values[i]) - } else if value != nil && len(*value) > 0 { - if err := json.Unmarshal(*value, &c.Strings); err != nil { - return fmt.Errorf("unmarshal field strings: %w", err) - } - } } } return nil @@ -174,6 +173,10 @@ func (c *Category) String() string { builder.WriteString(fmt.Sprintf("id=%v", c.ID)) builder.WriteString(", text=") builder.WriteString(c.Text) + if v := c.UUIDA; v != nil { + builder.WriteString(", uuid_a=") + builder.WriteString(fmt.Sprintf("%v", *v)) + } builder.WriteString(", status=") builder.WriteString(fmt.Sprintf("%v", c.Status)) builder.WriteString(", config=") @@ -182,8 +185,6 @@ func (c *Category) String() string { builder.WriteString(fmt.Sprintf("%v", c.Duration)) builder.WriteString(", count=") builder.WriteString(fmt.Sprintf("%v", c.Count)) - builder.WriteString(", strings=") - builder.WriteString(fmt.Sprintf("%v", c.Strings)) builder.WriteByte(')') return builder.String() } diff --git a/entgql/internal/todoplugin/ent/category/category.go b/entgql/internal/todoplugin/ent/category/category.go index 12f9be698..72e24c0b1 100644 --- a/entgql/internal/todoplugin/ent/category/category.go +++ b/entgql/internal/todoplugin/ent/category/category.go @@ -29,6 +29,8 @@ const ( FieldID = "id" // FieldText holds the string denoting the text field in the database. FieldText = "text" + // FieldUUIDA holds the string denoting the uuid_a field in the database. + FieldUUIDA = "uuid_a" // FieldStatus holds the string denoting the status field in the database. FieldStatus = "status" // FieldConfig holds the string denoting the config field in the database. @@ -37,8 +39,6 @@ const ( FieldDuration = "duration" // FieldCount holds the string denoting the count field in the database. FieldCount = "count" - // FieldStrings holds the string denoting the strings field in the database. - FieldStrings = "strings" // EdgeTodos holds the string denoting the todos edge name in mutations. EdgeTodos = "todos" // Table holds the table name of the category in the database. @@ -56,11 +56,11 @@ const ( var Columns = []string{ FieldID, FieldText, + FieldUUIDA, FieldStatus, FieldConfig, FieldDuration, FieldCount, - FieldStrings, } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/entgql/internal/todoplugin/ent/category/where.go b/entgql/internal/todoplugin/ent/category/where.go index 80739f7c0..04c3eb03b 100644 --- a/entgql/internal/todoplugin/ent/category/where.go +++ b/entgql/internal/todoplugin/ent/category/where.go @@ -23,6 +23,7 @@ import ( "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/google/uuid" ) // ID filters vertices based on their ID field. @@ -115,6 +116,13 @@ func Text(v string) predicate.Category { }) } +// UUIDA applies equality check predicate on the "uuid_a" field. It's identical to UUIDAEQ. +func UUIDA(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldUUIDA), v)) + }) +} + // Config applies equality check predicate on the "config" field. It's identical to ConfigEQ. func Config(v *schematype.CategoryConfig) predicate.Category { return predicate.Category(func(s *sql.Selector) { @@ -248,6 +256,96 @@ func TextContainsFold(v string) predicate.Category { }) } +// UUIDAEQ applies the EQ predicate on the "uuid_a" field. +func UUIDAEQ(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldUUIDA), v)) + }) +} + +// UUIDANEQ applies the NEQ predicate on the "uuid_a" field. +func UUIDANEQ(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldUUIDA), v)) + }) +} + +// UUIDAIn applies the In predicate on the "uuid_a" field. +func UUIDAIn(vs ...uuid.UUID) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldUUIDA), v...)) + }) +} + +// UUIDANotIn applies the NotIn predicate on the "uuid_a" field. +func UUIDANotIn(vs ...uuid.UUID) predicate.Category { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.Category(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldUUIDA), v...)) + }) +} + +// UUIDAGT applies the GT predicate on the "uuid_a" field. +func UUIDAGT(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldUUIDA), v)) + }) +} + +// UUIDAGTE applies the GTE predicate on the "uuid_a" field. +func UUIDAGTE(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldUUIDA), v)) + }) +} + +// UUIDALT applies the LT predicate on the "uuid_a" field. +func UUIDALT(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldUUIDA), v)) + }) +} + +// UUIDALTE applies the LTE predicate on the "uuid_a" field. +func UUIDALTE(v uuid.UUID) predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldUUIDA), v)) + }) +} + +// UUIDAIsNil applies the IsNil predicate on the "uuid_a" field. +func UUIDAIsNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldUUIDA))) + }) +} + +// UUIDANotNil applies the NotNil predicate on the "uuid_a" field. +func UUIDANotNil() predicate.Category { + return predicate.Category(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldUUIDA))) + }) +} + // StatusEQ applies the EQ predicate on the "status" field. func StatusEQ(v Status) predicate.Category { return predicate.Category(func(s *sql.Selector) { @@ -572,20 +670,6 @@ func CountNotNil() predicate.Category { }) } -// StringsIsNil applies the IsNil predicate on the "strings" field. -func StringsIsNil() predicate.Category { - return predicate.Category(func(s *sql.Selector) { - s.Where(sql.IsNull(s.C(FieldStrings))) - }) -} - -// StringsNotNil applies the NotNil predicate on the "strings" field. -func StringsNotNil() predicate.Category { - return predicate.Category(func(s *sql.Selector) { - s.Where(sql.NotNull(s.C(FieldStrings))) - }) -} - // HasTodos applies the HasEdge predicate on the "todos" edge. func HasTodos() predicate.Category { return predicate.Category(func(s *sql.Selector) { diff --git a/entgql/internal/todoplugin/ent/category_create.go b/entgql/internal/todoplugin/ent/category_create.go index a21327a60..a75eb08b7 100644 --- a/entgql/internal/todoplugin/ent/category_create.go +++ b/entgql/internal/todoplugin/ent/category_create.go @@ -27,6 +27,7 @@ import ( "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" + "github.com/google/uuid" ) // CategoryCreate is the builder for creating a Category entity. @@ -42,6 +43,12 @@ func (cc *CategoryCreate) SetText(s string) *CategoryCreate { return cc } +// SetUUIDA sets the "uuid_a" field. +func (cc *CategoryCreate) SetUUIDA(u uuid.UUID) *CategoryCreate { + cc.mutation.SetUUIDA(u) + return cc +} + // SetStatus sets the "status" field. func (cc *CategoryCreate) SetStatus(c category.Status) *CategoryCreate { cc.mutation.SetStatus(c) @@ -82,12 +89,6 @@ func (cc *CategoryCreate) SetNillableCount(u *uint64) *CategoryCreate { return cc } -// SetStrings sets the "strings" field. -func (cc *CategoryCreate) SetStrings(s []string) *CategoryCreate { - cc.mutation.SetStrings(s) - return cc -} - // AddTodoIDs adds the "todos" edge to the Todo entity by IDs. func (cc *CategoryCreate) AddTodoIDs(ids ...int) *CategoryCreate { cc.mutation.AddTodoIDs(ids...) @@ -224,6 +225,14 @@ func (cc *CategoryCreate) createSpec() (*Category, *sqlgraph.CreateSpec) { }) _node.Text = value } + if value, ok := cc.mutation.UUIDA(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Value: value, + Column: category.FieldUUIDA, + }) + _node.UUIDA = &value + } if value, ok := cc.mutation.Status(); ok { _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ Type: field.TypeEnum, @@ -256,14 +265,6 @@ func (cc *CategoryCreate) createSpec() (*Category, *sqlgraph.CreateSpec) { }) _node.Count = value } - if value, ok := cc.mutation.Strings(); ok { - _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ - Type: field.TypeJSON, - Value: value, - Column: category.FieldStrings, - }) - _node.Strings = value - } if nodes := cc.mutation.TodosIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, diff --git a/entgql/internal/todoplugin/ent/category_update.go b/entgql/internal/todoplugin/ent/category_update.go index 02ae0700e..ce0c52524 100644 --- a/entgql/internal/todoplugin/ent/category_update.go +++ b/entgql/internal/todoplugin/ent/category_update.go @@ -29,6 +29,7 @@ import ( "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" + "github.com/google/uuid" ) // CategoryUpdate is the builder for updating Category entities. @@ -50,6 +51,18 @@ func (cu *CategoryUpdate) SetText(s string) *CategoryUpdate { return cu } +// SetUUIDA sets the "uuid_a" field. +func (cu *CategoryUpdate) SetUUIDA(u uuid.UUID) *CategoryUpdate { + cu.mutation.SetUUIDA(u) + return cu +} + +// ClearUUIDA clears the value of the "uuid_a" field. +func (cu *CategoryUpdate) ClearUUIDA() *CategoryUpdate { + cu.mutation.ClearUUIDA() + return cu +} + // SetStatus sets the "status" field. func (cu *CategoryUpdate) SetStatus(c category.Status) *CategoryUpdate { cu.mutation.SetStatus(c) @@ -122,18 +135,6 @@ func (cu *CategoryUpdate) ClearCount() *CategoryUpdate { return cu } -// SetStrings sets the "strings" field. -func (cu *CategoryUpdate) SetStrings(s []string) *CategoryUpdate { - cu.mutation.SetStrings(s) - return cu -} - -// ClearStrings clears the value of the "strings" field. -func (cu *CategoryUpdate) ClearStrings() *CategoryUpdate { - cu.mutation.ClearStrings() - return cu -} - // AddTodoIDs adds the "todos" edge to the Todo entity by IDs. func (cu *CategoryUpdate) AddTodoIDs(ids ...int) *CategoryUpdate { cu.mutation.AddTodoIDs(ids...) @@ -275,6 +276,19 @@ func (cu *CategoryUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: category.FieldText, }) } + if value, ok := cu.mutation.UUIDA(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Value: value, + Column: category.FieldUUIDA, + }) + } + if cu.mutation.UUIDACleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: category.FieldUUIDA, + }) + } if value, ok := cu.mutation.Status(); ok { _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ Type: field.TypeEnum, @@ -335,19 +349,6 @@ func (cu *CategoryUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: category.FieldCount, }) } - if value, ok := cu.mutation.Strings(); ok { - _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ - Type: field.TypeJSON, - Value: value, - Column: category.FieldStrings, - }) - } - if cu.mutation.StringsCleared() { - _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ - Type: field.TypeJSON, - Column: category.FieldStrings, - }) - } if cu.mutation.TodosCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, @@ -427,6 +428,18 @@ func (cuo *CategoryUpdateOne) SetText(s string) *CategoryUpdateOne { return cuo } +// SetUUIDA sets the "uuid_a" field. +func (cuo *CategoryUpdateOne) SetUUIDA(u uuid.UUID) *CategoryUpdateOne { + cuo.mutation.SetUUIDA(u) + return cuo +} + +// ClearUUIDA clears the value of the "uuid_a" field. +func (cuo *CategoryUpdateOne) ClearUUIDA() *CategoryUpdateOne { + cuo.mutation.ClearUUIDA() + return cuo +} + // SetStatus sets the "status" field. func (cuo *CategoryUpdateOne) SetStatus(c category.Status) *CategoryUpdateOne { cuo.mutation.SetStatus(c) @@ -499,18 +512,6 @@ func (cuo *CategoryUpdateOne) ClearCount() *CategoryUpdateOne { return cuo } -// SetStrings sets the "strings" field. -func (cuo *CategoryUpdateOne) SetStrings(s []string) *CategoryUpdateOne { - cuo.mutation.SetStrings(s) - return cuo -} - -// ClearStrings clears the value of the "strings" field. -func (cuo *CategoryUpdateOne) ClearStrings() *CategoryUpdateOne { - cuo.mutation.ClearStrings() - return cuo -} - // AddTodoIDs adds the "todos" edge to the Todo entity by IDs. func (cuo *CategoryUpdateOne) AddTodoIDs(ids ...int) *CategoryUpdateOne { cuo.mutation.AddTodoIDs(ids...) @@ -676,6 +677,19 @@ func (cuo *CategoryUpdateOne) sqlSave(ctx context.Context) (_node *Category, err Column: category.FieldText, }) } + if value, ok := cuo.mutation.UUIDA(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Value: value, + Column: category.FieldUUIDA, + }) + } + if cuo.mutation.UUIDACleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: category.FieldUUIDA, + }) + } if value, ok := cuo.mutation.Status(); ok { _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ Type: field.TypeEnum, @@ -736,19 +750,6 @@ func (cuo *CategoryUpdateOne) sqlSave(ctx context.Context) (_node *Category, err Column: category.FieldCount, }) } - if value, ok := cuo.mutation.Strings(); ok { - _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ - Type: field.TypeJSON, - Value: value, - Column: category.FieldStrings, - }) - } - if cuo.mutation.StringsCleared() { - _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ - Type: field.TypeJSON, - Column: category.FieldStrings, - }) - } if cuo.mutation.TodosCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.O2M, diff --git a/entgql/internal/todoplugin/ent/gql_node.go b/entgql/internal/todoplugin/ent/gql_node.go index 1981401c6..3fd7d50f4 100644 --- a/entgql/internal/todoplugin/ent/gql_node.go +++ b/entgql/internal/todoplugin/ent/gql_node.go @@ -78,10 +78,18 @@ func (c *Category) Node(ctx context.Context) (node *Node, err error) { Name: "text", Value: string(buf), } - if buf, err = json.Marshal(c.Status); err != nil { + if buf, err = json.Marshal(c.UUIDA); err != nil { return nil, err } node.Fields[1] = &Field{ + Type: "uuid.UUID", + Name: "uuid_a", + Value: string(buf), + } + if buf, err = json.Marshal(c.Status); err != nil { + return nil, err + } + node.Fields[2] = &Field{ Type: "category.Status", Name: "status", Value: string(buf), @@ -89,7 +97,7 @@ func (c *Category) Node(ctx context.Context) (node *Node, err error) { if buf, err = json.Marshal(c.Config); err != nil { return nil, err } - node.Fields[2] = &Field{ + node.Fields[3] = &Field{ Type: "*schematype.CategoryConfig", Name: "config", Value: string(buf), @@ -97,7 +105,7 @@ func (c *Category) Node(ctx context.Context) (node *Node, err error) { if buf, err = json.Marshal(c.Duration); err != nil { return nil, err } - node.Fields[3] = &Field{ + node.Fields[4] = &Field{ Type: "time.Duration", Name: "duration", Value: string(buf), @@ -105,19 +113,11 @@ func (c *Category) Node(ctx context.Context) (node *Node, err error) { if buf, err = json.Marshal(c.Count); err != nil { return nil, err } - node.Fields[4] = &Field{ + node.Fields[5] = &Field{ Type: "uint64", Name: "count", Value: string(buf), } - if buf, err = json.Marshal(c.Strings); err != nil { - return nil, err - } - node.Fields[5] = &Field{ - Type: "[]string", - Name: "strings", - Value: string(buf), - } node.Edges[0] = &Edge{ Type: "Todo", Name: "todos", diff --git a/entgql/internal/todoplugin/ent/migrate/schema.go b/entgql/internal/todoplugin/ent/migrate/schema.go index 29a612287..62e4389a9 100644 --- a/entgql/internal/todoplugin/ent/migrate/schema.go +++ b/entgql/internal/todoplugin/ent/migrate/schema.go @@ -26,11 +26,11 @@ var ( CategoriesColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt, Increment: true}, {Name: "text", Type: field.TypeString, Size: 2147483647}, + {Name: "uuid_a", Type: field.TypeUUID, Nullable: true}, {Name: "status", Type: field.TypeEnum, Enums: []string{"ENABLED", "DISABLED"}}, {Name: "config", Type: field.TypeOther, Nullable: true, SchemaType: map[string]string{"sqlite3": "json"}}, {Name: "duration", Type: field.TypeInt64, Nullable: true}, {Name: "count", Type: field.TypeUint64, Nullable: true}, - {Name: "strings", Type: field.TypeJSON, Nullable: true}, } // CategoriesTable holds the schema information for the "categories" table. CategoriesTable = &schema.Table{ diff --git a/entgql/internal/todoplugin/ent/mutation.go b/entgql/internal/todoplugin/ent/mutation.go index 30ba87cfe..34a0f666e 100644 --- a/entgql/internal/todoplugin/ent/mutation.go +++ b/entgql/internal/todoplugin/ent/mutation.go @@ -30,6 +30,7 @@ import ( "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "entgo.io/contrib/entgql/internal/todoplugin/ent/user" + "github.com/google/uuid" "entgo.io/ent" ) @@ -55,13 +56,13 @@ type CategoryMutation struct { typ string id *int text *string + uuid_a *uuid.UUID status *category.Status _config **schematype.CategoryConfig duration *time.Duration addduration *time.Duration count *uint64 addcount *int64 - strings *[]string clearedFields map[string]struct{} todos map[int]struct{} removedtodos map[int]struct{} @@ -205,6 +206,55 @@ func (m *CategoryMutation) ResetText() { m.text = nil } +// SetUUIDA sets the "uuid_a" field. +func (m *CategoryMutation) SetUUIDA(u uuid.UUID) { + m.uuid_a = &u +} + +// UUIDA returns the value of the "uuid_a" field in the mutation. +func (m *CategoryMutation) UUIDA() (r uuid.UUID, exists bool) { + v := m.uuid_a + if v == nil { + return + } + return *v, true +} + +// OldUUIDA returns the old "uuid_a" field's value of the Category entity. +// If the Category object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *CategoryMutation) OldUUIDA(ctx context.Context) (v *uuid.UUID, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldUUIDA is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldUUIDA requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldUUIDA: %w", err) + } + return oldValue.UUIDA, nil +} + +// ClearUUIDA clears the value of the "uuid_a" field. +func (m *CategoryMutation) ClearUUIDA() { + m.uuid_a = nil + m.clearedFields[category.FieldUUIDA] = struct{}{} +} + +// UUIDACleared returns if the "uuid_a" field was cleared in this mutation. +func (m *CategoryMutation) UUIDACleared() bool { + _, ok := m.clearedFields[category.FieldUUIDA] + return ok +} + +// ResetUUIDA resets all changes to the "uuid_a" field. +func (m *CategoryMutation) ResetUUIDA() { + m.uuid_a = nil + delete(m.clearedFields, category.FieldUUIDA) +} + // SetStatus sets the "status" field. func (m *CategoryMutation) SetStatus(c category.Status) { m.status = &c @@ -430,55 +480,6 @@ func (m *CategoryMutation) ResetCount() { delete(m.clearedFields, category.FieldCount) } -// SetStrings sets the "strings" field. -func (m *CategoryMutation) SetStrings(s []string) { - m.strings = &s -} - -// Strings returns the value of the "strings" field in the mutation. -func (m *CategoryMutation) Strings() (r []string, exists bool) { - v := m.strings - if v == nil { - return - } - return *v, true -} - -// OldStrings returns the old "strings" field's value of the Category entity. -// If the Category object wasn't provided to the builder, the object is fetched from the database. -// An error is returned if the mutation operation is not UpdateOne, or the database query fails. -func (m *CategoryMutation) OldStrings(ctx context.Context) (v []string, err error) { - if !m.op.Is(OpUpdateOne) { - return v, errors.New("OldStrings is only allowed on UpdateOne operations") - } - if m.id == nil || m.oldValue == nil { - return v, errors.New("OldStrings requires an ID field in the mutation") - } - oldValue, err := m.oldValue(ctx) - if err != nil { - return v, fmt.Errorf("querying old value for OldStrings: %w", err) - } - return oldValue.Strings, nil -} - -// ClearStrings clears the value of the "strings" field. -func (m *CategoryMutation) ClearStrings() { - m.strings = nil - m.clearedFields[category.FieldStrings] = struct{}{} -} - -// StringsCleared returns if the "strings" field was cleared in this mutation. -func (m *CategoryMutation) StringsCleared() bool { - _, ok := m.clearedFields[category.FieldStrings] - return ok -} - -// ResetStrings resets all changes to the "strings" field. -func (m *CategoryMutation) ResetStrings() { - m.strings = nil - delete(m.clearedFields, category.FieldStrings) -} - // AddTodoIDs adds the "todos" edge to the Todo entity by ids. func (m *CategoryMutation) AddTodoIDs(ids ...int) { if m.todos == nil { @@ -556,6 +557,9 @@ func (m *CategoryMutation) Fields() []string { if m.text != nil { fields = append(fields, category.FieldText) } + if m.uuid_a != nil { + fields = append(fields, category.FieldUUIDA) + } if m.status != nil { fields = append(fields, category.FieldStatus) } @@ -568,9 +572,6 @@ func (m *CategoryMutation) Fields() []string { if m.count != nil { fields = append(fields, category.FieldCount) } - if m.strings != nil { - fields = append(fields, category.FieldStrings) - } return fields } @@ -581,6 +582,8 @@ func (m *CategoryMutation) Field(name string) (ent.Value, bool) { switch name { case category.FieldText: return m.Text() + case category.FieldUUIDA: + return m.UUIDA() case category.FieldStatus: return m.Status() case category.FieldConfig: @@ -589,8 +592,6 @@ func (m *CategoryMutation) Field(name string) (ent.Value, bool) { return m.Duration() case category.FieldCount: return m.Count() - case category.FieldStrings: - return m.Strings() } return nil, false } @@ -602,6 +603,8 @@ func (m *CategoryMutation) OldField(ctx context.Context, name string) (ent.Value switch name { case category.FieldText: return m.OldText(ctx) + case category.FieldUUIDA: + return m.OldUUIDA(ctx) case category.FieldStatus: return m.OldStatus(ctx) case category.FieldConfig: @@ -610,8 +613,6 @@ func (m *CategoryMutation) OldField(ctx context.Context, name string) (ent.Value return m.OldDuration(ctx) case category.FieldCount: return m.OldCount(ctx) - case category.FieldStrings: - return m.OldStrings(ctx) } return nil, fmt.Errorf("unknown Category field %s", name) } @@ -628,6 +629,13 @@ func (m *CategoryMutation) SetField(name string, value ent.Value) error { } m.SetText(v) return nil + case category.FieldUUIDA: + v, ok := value.(uuid.UUID) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetUUIDA(v) + return nil case category.FieldStatus: v, ok := value.(category.Status) if !ok { @@ -656,13 +664,6 @@ func (m *CategoryMutation) SetField(name string, value ent.Value) error { } m.SetCount(v) return nil - case category.FieldStrings: - v, ok := value.([]string) - if !ok { - return fmt.Errorf("unexpected type %T for field %s", value, name) - } - m.SetStrings(v) - return nil } return fmt.Errorf("unknown Category field %s", name) } @@ -720,6 +721,9 @@ func (m *CategoryMutation) AddField(name string, value ent.Value) error { // mutation. func (m *CategoryMutation) ClearedFields() []string { var fields []string + if m.FieldCleared(category.FieldUUIDA) { + fields = append(fields, category.FieldUUIDA) + } if m.FieldCleared(category.FieldConfig) { fields = append(fields, category.FieldConfig) } @@ -729,9 +733,6 @@ func (m *CategoryMutation) ClearedFields() []string { if m.FieldCleared(category.FieldCount) { fields = append(fields, category.FieldCount) } - if m.FieldCleared(category.FieldStrings) { - fields = append(fields, category.FieldStrings) - } return fields } @@ -746,6 +747,9 @@ func (m *CategoryMutation) FieldCleared(name string) bool { // error if the field is not defined in the schema. func (m *CategoryMutation) ClearField(name string) error { switch name { + case category.FieldUUIDA: + m.ClearUUIDA() + return nil case category.FieldConfig: m.ClearConfig() return nil @@ -755,9 +759,6 @@ func (m *CategoryMutation) ClearField(name string) error { case category.FieldCount: m.ClearCount() return nil - case category.FieldStrings: - m.ClearStrings() - return nil } return fmt.Errorf("unknown Category nullable field %s", name) } @@ -769,6 +770,9 @@ func (m *CategoryMutation) ResetField(name string) error { case category.FieldText: m.ResetText() return nil + case category.FieldUUIDA: + m.ResetUUIDA() + return nil case category.FieldStatus: m.ResetStatus() return nil @@ -781,9 +785,6 @@ func (m *CategoryMutation) ResetField(name string) error { case category.FieldCount: m.ResetCount() return nil - case category.FieldStrings: - m.ResetStrings() - return nil } return fmt.Errorf("unknown Category field %s", name) } diff --git a/entgql/internal/todoplugin/ent/schema/category.go b/entgql/internal/todoplugin/ent/schema/category.go index 3dc918bf1..f58d583ea 100644 --- a/entgql/internal/todoplugin/ent/schema/category.go +++ b/entgql/internal/todoplugin/ent/schema/category.go @@ -23,6 +23,7 @@ import ( "entgo.io/ent/schema" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" + "github.com/google/uuid" "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" ) @@ -40,6 +41,9 @@ func (Category) Fields() []ent.Field { Annotations( entgql.OrderField("TEXT"), ), + field.UUID("uuid_a", uuid.New()). + Nillable(). + Optional(), field.Enum("status"). NamedValues( "Enabled", "ENABLED", @@ -52,10 +56,7 @@ func (Category) Fields() []ent.Field { SchemaType(map[string]string{ dialect.SQLite: "json", }). - Optional(). - Annotations( - entgql.Type("CategoryConfig"), - ), + Optional(), field.Int64("duration"). GoType(time.Duration(0)). Optional(). @@ -68,8 +69,8 @@ func (Category) Fields() []ent.Field { Annotations( entgql.Type("Uint64"), ), - field.Strings("strings"). - Optional(), + // field.Strings("strings"). + // Optional(), } } diff --git a/entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go b/entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go new file mode 100644 index 000000000..e19de6d33 --- /dev/null +++ b/entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go @@ -0,0 +1,38 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package uuidgql + +import ( + "fmt" + "io" + "strconv" + + "github.com/99designs/gqlgen/graphql" + "github.com/google/uuid" +) + +func MarshalUUID(u uuid.UUID) graphql.Marshaler { + return graphql.WriterFunc(func(w io.Writer) { + _, _ = io.WriteString(w, strconv.Quote(u.String())) + }) +} + +func UnmarshalUUID(v interface{}) (u uuid.UUID, err error) { + s, ok := v.(string) + if !ok { + return u, fmt.Errorf("invalid type %T, expect string", v) + } + return uuid.Parse(s) +} diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go index 14c15d4da..29071da1d 100644 --- a/entgql/internal/todoplugin/generated.go +++ b/entgql/internal/todoplugin/generated.go @@ -13,11 +13,15 @@ import ( "time" "entgo.io/contrib/entgql/internal/todoplugin/ent" + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" "entgo.io/contrib/entgql/internal/todoplugin/ent/role" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/durationgql" "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/uuidgql" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "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" ) @@ -52,9 +56,13 @@ type DirectiveRoot struct { type ComplexityRoot struct { Category struct { - ID func(childComplexity int) int - Strings func(childComplexity int) int - Text func(childComplexity int) int + Config func(childComplexity int) int + Count func(childComplexity int) int + Duration func(childComplexity int) int + ID func(childComplexity int) int + Status func(childComplexity int) int + Text func(childComplexity int) int + UUIDA func(childComplexity int) int } CategoryConfig struct { @@ -142,6 +150,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in _ = ec switch typeName + "." + field { + case "Category.config": + if e.complexity.Category.Config == nil { + break + } + + return e.complexity.Category.Config(childComplexity), true + + case "Category.count": + if e.complexity.Category.Count == nil { + break + } + + return e.complexity.Category.Count(childComplexity), true + + case "Category.duration": + if e.complexity.Category.Duration == nil { + break + } + + return e.complexity.Category.Duration(childComplexity), true + case "Category.id": if e.complexity.Category.ID == nil { break @@ -149,12 +178,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Category.ID(childComplexity), true - case "Category.strings": - if e.complexity.Category.Strings == nil { + case "Category.status": + if e.complexity.Category.Status == nil { break } - return e.complexity.Category.Strings(childComplexity), true + return e.complexity.Category.Status(childComplexity), true case "Category.text": if e.complexity.Category.Text == nil { @@ -163,6 +192,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Category.Text(childComplexity), true + case "Category.uuidA": + if e.complexity.Category.UUIDA == nil { + break + } + + return e.complexity.Category.UUIDA(childComplexity), true + case "CategoryConfig.maxMembers": if e.complexity.CategoryConfig.MaxMembers == nil { break @@ -443,10 +479,10 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ - {Name: "todo.graphql", Input: `directive @someDirective(stringArg: String, boolArg: Boolean) on OBJECT - | INPUT_OBJECT - | SCALAR - | FIELD_DEFINITION + {Name: "todo.graphql", Input: `directive @someDirective( + stringArg: String + boolArg: Boolean +) on OBJECT | INPUT_OBJECT | SCALAR | FIELD_DEFINITION interface Node { id: ID! @@ -473,6 +509,7 @@ enum Status { scalar Time scalar Duration scalar Uint64 +scalar UUID type Todo implements Node { id: ID! @@ -488,7 +525,12 @@ type Todo implements Node { type Category implements Node { id: ID! text: String! - strings: [String] + uuidA: UUID + status: CategoryStatus! + config: CategoryConfig! + duration: Duration! + count: Uint64! + # strings: [String] } input TodoInput { @@ -537,23 +579,29 @@ input TodoOrder { } enum Role { - ADMIN - USER - UNKNOWN + ADMIN + USER + UNKNOWN } type User implements Node { - id: ID! - username: String! - age: Float! - amount: Float! - role: Role! + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! } type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! - todos(after: Cursor, first: Int, before: Cursor, last: Int, orderBy: TodoOrder): TodoConnection + todos( + after: Cursor + first: Int + before: Cursor + last: Int + orderBy: TodoOrder + ): TodoConnection } type Mutation { @@ -826,7 +874,7 @@ func (ec *executionContext) _Category_text(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Category_strings(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { +func (ec *executionContext) _Category_uuidA(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -844,7 +892,7 @@ func (ec *executionContext) _Category_strings(ctx context.Context, field graphql ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Strings, nil + return obj.UUIDA, nil }) if err != nil { ec.Error(ctx, err) @@ -853,9 +901,149 @@ func (ec *executionContext) _Category_strings(ctx context.Context, field graphql if resTmp == nil { return graphql.Null } - res := resTmp.([]string) + res := resTmp.(*uuid.UUID) + fc.Result = res + return ec.marshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res) +} + +func (ec *executionContext) _Category_status(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Status, 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.(category.Status) + fc.Result = res + return ec.marshalNCategoryStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋcategoryᚐStatus(ctx, field.Selections, res) +} + +func (ec *executionContext) _Category_config(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Config, 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.(*schematype.CategoryConfig) + fc.Result = res + return ec.marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋschemaᚋschematypeᚐCategoryConfig(ctx, field.Selections, res) +} + +func (ec *executionContext) _Category_duration(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Duration, 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.(time.Duration) + fc.Result = res + return ec.marshalNDuration2timeᚐDuration(ctx, field.Selections, res) +} + +func (ec *executionContext) _Category_count(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Category", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Count, 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.(uint64) fc.Result = res - return ec.marshalOString2ᚕstring(ctx, field.Selections, res) + return ec.marshalNUint642uint64(ctx, field.Selections, res) } func (ec *executionContext) _CategoryConfig_maxMembers(ctx context.Context, field graphql.CollectedField, obj *schematype.CategoryConfig) (ret graphql.Marshaler) { @@ -3208,13 +3396,53 @@ func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { invalids++ } - case "strings": + case "uuidA": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_uuidA(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "status": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_status(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "config": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_config(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "duration": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_duration(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "count": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_strings(ctx, field, obj) + return ec._Category_count(ctx, field, obj) } out.Values[i] = innerFunc(ctx) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -4186,6 +4414,26 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } +func (ec *executionContext) marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋschemaᚋschematypeᚐCategoryConfig(ctx context.Context, sel ast.SelectionSet, v *schematype.CategoryConfig) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._CategoryConfig(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNCategoryStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋcategoryᚐStatus(ctx context.Context, v interface{}) (category.Status, error) { + var res category.Status + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCategoryStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋcategoryᚐStatus(ctx context.Context, sel ast.SelectionSet, v category.Status) graphql.Marshaler { + return v +} + func (ec *executionContext) unmarshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx context.Context, v interface{}) (ent.Cursor, error) { var res ent.Cursor err := res.UnmarshalGQL(v) @@ -4196,6 +4444,21 @@ func (ec *executionContext) marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinter return v } +func (ec *executionContext) unmarshalNDuration2timeᚐDuration(ctx context.Context, v interface{}) (time.Duration, error) { + res, err := durationgql.UnmarshalDuration(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNDuration2timeᚐDuration(ctx context.Context, sel ast.SelectionSet, v time.Duration) graphql.Marshaler { + res := durationgql.MarshalDuration(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + func (ec *executionContext) unmarshalNFloat2float64(ctx context.Context, v interface{}) (float64, error) { res, err := graphql.UnmarshalFloatContext(ctx, v) return res, graphql.ErrorOnPath(ctx, err) @@ -4379,6 +4642,21 @@ func (ec *executionContext) unmarshalNTodoInput2entgoᚗioᚋcontribᚋentgqlᚋ return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNUint642uint64(ctx context.Context, v interface{}) (uint64, error) { + res, err := graphql.UnmarshalUint64(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNUint642uint64(ctx context.Context, sel ast.SelectionSet, v uint64) graphql.Marshaler { + res := graphql.MarshalUint64(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + 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) } @@ -4740,38 +5018,6 @@ func (ec *executionContext) marshalOString2string(ctx context.Context, sel ast.S return res } -func (ec *executionContext) unmarshalOString2ᚕstring(ctx context.Context, v interface{}) ([]string, error) { - if v == nil { - return nil, nil - } - 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.unmarshalOString2string(ctx, vSlice[i]) - if err != nil { - return nil, err - } - } - return res, nil -} - -func (ec *executionContext) marshalOString2ᚕstring(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - for i := range v { - ret[i] = ec.marshalOString2string(ctx, sel, v[i]) - } - - return ret -} - func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil @@ -4931,6 +5177,22 @@ func (ec *executionContext) marshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋent return v } +func (ec *executionContext) unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, v interface{}) (*uuid.UUID, error) { + if v == nil { + return nil, nil + } + res, err := uuidgql.UnmarshalUUID(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, sel ast.SelectionSet, v *uuid.UUID) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := uuidgql.MarshalUUID(*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 diff --git a/entgql/internal/todoplugin/gqlgen.yml b/entgql/internal/todoplugin/gqlgen.yml index d0b892632..ee75a4cd3 100644 --- a/entgql/internal/todoplugin/gqlgen.yml +++ b/entgql/internal/todoplugin/gqlgen.yml @@ -25,6 +25,9 @@ models: Duration: model: - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/durationgql.Duration + UUID: + model: + - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/uuidgql.UUID Node: model: - entgo.io/contrib/entgql/internal/todoplugin/ent.Noder diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql index 993be2ccb..11c677eb2 100644 --- a/entgql/internal/todoplugin/todo.graphql +++ b/entgql/internal/todoplugin/todo.graphql @@ -1,7 +1,7 @@ -directive @someDirective(stringArg: String, boolArg: Boolean) on OBJECT - | INPUT_OBJECT - | SCALAR - | FIELD_DEFINITION +directive @someDirective( + stringArg: String + boolArg: Boolean +) on OBJECT | INPUT_OBJECT | SCALAR | FIELD_DEFINITION interface Node { id: ID! @@ -28,6 +28,7 @@ enum Status { scalar Time scalar Duration scalar Uint64 +scalar UUID type Todo implements Node { id: ID! @@ -43,7 +44,12 @@ type Todo implements Node { type Category implements Node { id: ID! text: String! - strings: [String] + uuidA: UUID + status: CategoryStatus! + config: CategoryConfig! + duration: Duration! + count: Uint64! + # strings: [String] } input TodoInput { @@ -92,23 +98,29 @@ input TodoOrder { } enum Role { - ADMIN - USER - UNKNOWN + ADMIN + USER + UNKNOWN } type User implements Node { - id: ID! - username: String! - age: Float! - amount: Float! - role: Role! + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! } type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! - todos(after: Cursor, first: Int, before: Cursor, last: Int, orderBy: TodoOrder): TodoConnection + todos( + after: Cursor + first: Int + before: Cursor + last: Int + orderBy: TodoOrder + ): TodoConnection } type Mutation { diff --git a/entgql/internal/todoplugin/todo_test.go b/entgql/internal/todoplugin/todo_test.go index c968836c8..bec4e5062 100644 --- a/entgql/internal/todoplugin/todo_test.go +++ b/entgql/internal/todoplugin/todo_test.go @@ -781,7 +781,7 @@ func (s *todoTestSuite) TestMutationFieldCollection() { func (s *todoTestSuite) TestQueryJSONFields() { var ( ctx = context.Background() - cat = s.ent.Category.Create().SetText("Disabled").SetStatus(category.StatusDisabled).SetStrings([]string{"a", "b"}).SetText("category").SaveX(ctx) + cat = s.ent.Category.Create().SetText("Disabled").SetStatus(category.StatusDisabled).SetText("category").SaveX(ctx) rsp struct { Node struct { Text string @@ -793,11 +793,10 @@ func (s *todoTestSuite) TestQueryJSONFields() { node(id: $id) { ... on Category { text - strings + # strings } } }`, &rsp, client.Var("id", cat.ID)) s.Require().NoError(err) s.Require().Equal(cat.Text, rsp.Node.Text) - s.Require().Equal(cat.Strings, rsp.Node.Strings) } From 8a6de4f7315abcb7b9ce4775228cfb20795c5d6c Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 21:21:24 +0000 Subject: [PATCH 05/23] feat: build basic GQL types from the graph --- entgql/plugin/plugin.go | 170 ++++++++++++++++++++++++++++++++++- entgql/plugin/plugin_test.go | 62 +++++++++++++ 2 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 entgql/plugin/plugin_test.go diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index 1e67e720b..d9a699f56 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -15,17 +15,23 @@ package plugin import ( + "fmt" + "strings" + "entgo.io/contrib/entgql" "entgo.io/ent/entc/gen" + "entgo.io/ent/schema/field" "github.com/99designs/gqlgen/plugin" "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/formatter" ) type ( // EntGQL is a plugin that generates GQL schema from the Ent's Graph EntGQL struct { - graph *gen.Graph - nodes []*gen.Type + graph *gen.Graph + nodes []*gen.Type + schema *ast.Schema } // EntGQLPluginOption is a option for the EntGQL plugin @@ -33,6 +39,8 @@ type ( ) var ( + camel = gen.Funcs["camel"].(func(string) string) + _ plugin.Plugin = (*EntGQL)(nil) _ plugin.EarlySourceInjector = (*EntGQL)(nil) ) @@ -54,6 +62,14 @@ func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLPluginOption) (*EntGQL, err } } + types, err := e.buildTypes() + if err != nil { + return nil, err + } + + e.schema = &ast.Schema{ + Types: types, + } return e, nil } @@ -65,4 +81,154 @@ func (*EntGQL) Name() string { // InjectSourceEarly implements the EarlySourceInjector interface. func (e *EntGQL) InjectSourceEarly() *ast.Source { return nil + // return &ast.Source{ + // Name: "entgql.graphql", + // Input: printSchema(e.schema), + // BuiltIn: false, + // } +} + +func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { + types := map[string]*ast.Definition{} + for _, node := range e.nodes { + ant, err := decodeAnnotation(node.Annotations) + if err != nil { + return nil, err + } + if ant.Skip { + continue + } + + fields, err := e.buildTypeFields(node) + if err != nil { + return nil, err + } + + name := node.Name + if ant.Type != "" { + name = ant.Type + } + + var interfaces []string + types[name] = &ast.Definition{ + Name: name, + Kind: ast.Object, + Fields: fields, + Interfaces: interfaces, + } + } + + return types, nil +} + +func (e *EntGQL) buildTypeFields(t *gen.Type) (ast.FieldList, error) { + var fields ast.FieldList + if t.ID != nil { + f, err := e.typeField(t.ID, true) + if err != nil { + return nil, err + } + if f != nil { + fields = append(fields, f...) + } + } + + for _, f := range t.Fields { + f, err := e.typeField(f, false) + if err != nil { + return nil, err + } + if f != nil { + fields = append(fields, f...) + } + } + return fields, nil +} + +func (e *EntGQL) typeField(f *gen.Field, isID bool) ([]*ast.FieldDefinition, error) { + ant, err := decodeAnnotation(f.Annotations) + if err != nil { + return nil, err + } + if ant.Skip { + return nil, nil + } + + ft, err := typeFromField(f, isID, ant.Type) + if err != nil { + return nil, fmt.Errorf("field(%s): %w", f.Name, err) + } + + // TODO(giautm): support rename field + // TODO(giautm): support mapping single field to multiple GQL fields + return []*ast.FieldDefinition{ + { + Name: camel(f.Name), + Type: ft, + }, + }, nil +} + +func namedType(name string, nullable bool) *ast.Type { + if nullable { + return ast.NamedType(name, nil) + } + return ast.NonNullNamedType(name, nil) +} + +func typeFromField(f *gen.Field, idField bool, userDefinedType string) (*ast.Type, error) { + nillable := f.Nillable + typ := f.Type.Type + + // TODO(giautm): Support custom scalar types + // TODO(giautm): Support Edge Field + // TODO(giautm): Support nullable ID for non-relay + // TODO(giautm): Support some built-in JSON types: Ints(), Floats(), Strings() + scalar := f.Type.String() + switch { + case userDefinedType != "": + return namedType(userDefinedType, nillable), nil + case idField: + return namedType("ID", false), nil + case typ.Float(): + return namedType("Float", nillable), nil + case typ.Integer(): + return namedType("Int", nillable), nil + case typ == field.TypeString: + return namedType("String", nillable), nil + case typ == field.TypeBool: + return namedType("Boolean", nillable), nil + case typ == field.TypeBytes: + return nil, fmt.Errorf("bytes type not implemented") + case strings.ContainsRune(scalar, '.'): // Time, Enum or Other. + scalar = scalar[strings.LastIndexByte(scalar, '.')+1:] + return namedType(scalar, nillable), nil + case typ == field.TypeJSON: + return nil, fmt.Errorf("json type not implemented") + case typ == field.TypeOther: + return nil, fmt.Errorf("other type must have typed defined") + default: + return nil, fmt.Errorf("unexpected type: %s", typ.String()) + } +} + +func decodeAnnotation(annotations gen.Annotations) (*entgql.Annotation, error) { + ant := &entgql.Annotation{} + if annotations == nil || annotations[ant.Name()] == nil { + return ant, nil + } + + err := ant.Decode(annotations[ant.Name()]) + if err != nil { + return nil, err + } + return ant, nil +} + +func printSchema(schema *ast.Schema) string { + sb := &strings.Builder{} + formatter. + NewFormatter(sb). + FormatSchema(schema) + return sb.String() } diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go new file mode 100644 index 000000000..448f56f51 --- /dev/null +++ b/entgql/plugin/plugin_test.go @@ -0,0 +1,62 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "testing" + + "entgo.io/ent/entc" + "entgo.io/ent/entc/gen" + "github.com/stretchr/testify/require" + "github.com/vektah/gqlparser/v2/ast" +) + +func TestEntGQL_buildTypes(t *testing.T) { + graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) + require.NoError(t, err) + plugin, err := NewEntGQLPlugin(graph) + + require.NoError(t, err) + types, err := plugin.buildTypes() + require.NoError(t, err) + + require.Equal(t, `type Category { + id: ID! + text: String! + uuidA: UUID + status: CategoryStatus! + config: CategoryConfig! + duration: Duration! + count: Uint64! +} +type Todo { + id: ID! + createdAt: Time! + visibilityStatus: VisibilityStatus! + status: Status! + priority: Int! + text: String! +} +type User { + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! +} +`, printSchema(&ast.Schema{ + Types: types, + })) +} From e656db09df28ffacafcce575483a1c6321b96faa Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 21:55:57 +0000 Subject: [PATCH 06/23] feat: add a test for Type annotation on the entity --- entgql/internal/todoplugin/ent/schema/user.go | 8 ++ entgql/plugin/plugin.go | 4 +- entgql/plugin/plugin_config.go | 48 +++++++ entgql/plugin/plugin_config_test.go | 119 ++++++++++++++++++ entgql/plugin/plugin_test.go | 14 +-- 5 files changed, 185 insertions(+), 8 deletions(-) create mode 100644 entgql/plugin/plugin_config.go create mode 100644 entgql/plugin/plugin_config_test.go diff --git a/entgql/internal/todoplugin/ent/schema/user.go b/entgql/internal/todoplugin/ent/schema/user.go index f90493e21..56def1663 100644 --- a/entgql/internal/todoplugin/ent/schema/user.go +++ b/entgql/internal/todoplugin/ent/schema/user.go @@ -18,6 +18,7 @@ import ( "entgo.io/contrib/entgql" "entgo.io/contrib/entgql/internal/todoplugin/ent/role" "entgo.io/ent" + "entgo.io/ent/schema" "entgo.io/ent/schema/field" ) @@ -45,3 +46,10 @@ func (User) Fields() []ent.Field { GoType(role.Unknown), } } + +// Annotations returns user annotations. +func (User) Annotations() []schema.Annotation { + return []schema.Annotation{ + entgql.Type("MasterUser"), + } +} diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index d9a699f56..36eddfc2b 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -39,10 +39,12 @@ type ( ) var ( - camel = gen.Funcs["camel"].(func(string) string) + annotationName = entgql.Annotation{}.Name() + camel = gen.Funcs["camel"].(func(string) string) _ plugin.Plugin = (*EntGQL)(nil) _ plugin.EarlySourceInjector = (*EntGQL)(nil) + _ plugin.ConfigMutator = (*EntGQL)(nil) ) // NewEntGQLPlugin creates a new EntGQL plugin diff --git a/entgql/plugin/plugin_config.go b/entgql/plugin/plugin_config.go new file mode 100644 index 000000000..be014e1e1 --- /dev/null +++ b/entgql/plugin/plugin_config.go @@ -0,0 +1,48 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "fmt" + + "github.com/99designs/gqlgen/codegen/config" +) + +// MutateConfig implements the ConfigMutator interface +func (e *EntGQL) MutateConfig(cfg *config.Config) error { + for _, node := range e.nodes { + ant, err := decodeAnnotation(node.Annotations) + if err != nil { + return err + } + if ant.Skip { + continue + } + + name := node.Name + if ant.Type != "" { + name = ant.Type + } + if !cfg.Models.Exists(name) { + cfg.Models.Add(name, e.entGoType(node.Name)) + } + } + + return nil +} + +func (e *EntGQL) entGoType(name string) string { + return fmt.Sprintf("%s.%s", e.graph.Package, name) +} diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go new file mode 100644 index 000000000..71520a28b --- /dev/null +++ b/entgql/plugin/plugin_config_test.go @@ -0,0 +1,119 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "testing" + + "entgo.io/ent/entc/gen" + "entgo.io/ent/schema/field" + "github.com/99designs/gqlgen/codegen/config" + "github.com/stretchr/testify/require" +) + +func TestModifyConfig_empty(t *testing.T) { + e, err := NewEntGQLPlugin(&gen.Graph{ + Config: &gen.Config{ + Package: "example.com", + }, + }) + require.NoError(t, err) + cfg := config.DefaultConfig() + err = e.MutateConfig(cfg) + require.NoError(t, err) + expected := config.DefaultConfig() + expected.Models = map[string]config.TypeMapEntry{} + require.Equal(t, expected, cfg) +} + +func TestModifyConfig(t *testing.T) { + e, err := NewEntGQLPlugin(&gen.Graph{ + Config: &gen.Config{ + Package: "example.com", + IDType: &field.TypeInfo{ + Type: field.TypeInt, + }, + }, + Nodes: []*gen.Type{ + { + Name: "Todo", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + }, + { + Name: "User", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "Skip": true, + }, + }, + }, + { + Name: "Group", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, + }, + }, + { + Name: "GroupWithSort", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "OrderField": "NAME", + }, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, + }, + }, + }, + }) + require.NoError(t, err) + cfg := config.DefaultConfig() + err = e.MutateConfig(cfg) + require.NoError(t, err) + expected := config.DefaultConfig() + expected.Models = map[string]config.TypeMapEntry{ + "Todo": {Model: []string{"example.com.Todo"}}, + "Group": {Model: []string{"example.com.Group"}}, + "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, + } + require.Equal(t, expected, cfg) +} diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go index 448f56f51..5c0ab5d52 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/plugin/plugin_test.go @@ -41,6 +41,13 @@ func TestEntGQL_buildTypes(t *testing.T) { duration: Duration! count: Uint64! } +type MasterUser { + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! +} type Todo { id: ID! createdAt: Time! @@ -49,13 +56,6 @@ type Todo { priority: Int! text: String! } -type User { - id: ID! - username: String! - age: Float! - amount: Float! - role: Role! -} `, printSchema(&ast.Schema{ Types: types, })) From add22b7648c8c4a33094a75c2e9a9f4937a678ec Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 22:24:26 +0000 Subject: [PATCH 07/23] fix: added relaySpec flag --- entgql/internal/todoplugin/ent/mutation.go | 6 ++ entgql/internal/todoplugin/ent/schema/user.go | 4 + entgql/internal/todoplugin/ent/user/where.go | 14 ++++ entgql/internal/todoplugin/ent/user_create.go | 26 +++++- entgql/plugin/plugin.go | 21 ++++- entgql/plugin/plugin_config.go | 22 +++++ entgql/plugin/plugin_config_test.go | 83 +++++++++++++++++++ entgql/plugin/plugin_test.go | 40 ++++++++- 8 files changed, 208 insertions(+), 8 deletions(-) diff --git a/entgql/internal/todoplugin/ent/mutation.go b/entgql/internal/todoplugin/ent/mutation.go index 34a0f666e..1c26346ea 100644 --- a/entgql/internal/todoplugin/ent/mutation.go +++ b/entgql/internal/todoplugin/ent/mutation.go @@ -1676,6 +1676,12 @@ func (m UserMutation) Tx() (*Tx, error) { return tx, nil } +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of User entities. +func (m *UserMutation) SetID(id int) { + m.id = &id +} + // ID returns the ID value in the mutation. Note that the ID is only available // if it was provided to the builder or after it was returned from the database. func (m *UserMutation) ID() (id int, exists bool) { diff --git a/entgql/internal/todoplugin/ent/schema/user.go b/entgql/internal/todoplugin/ent/schema/user.go index 56def1663..e9fe108e6 100644 --- a/entgql/internal/todoplugin/ent/schema/user.go +++ b/entgql/internal/todoplugin/ent/schema/user.go @@ -32,6 +32,10 @@ type User struct { // Fields returns User fields. func (User) Fields() []ent.Field { return []ent.Field{ + field.Int("id"). + Nillable(). + Optional(). + Unique(), field.String("username"), field.Int("age"). Annotations(entgql.Annotation{ diff --git a/entgql/internal/todoplugin/ent/user/where.go b/entgql/internal/todoplugin/ent/user/where.go index bba85a4d9..115b1956c 100644 --- a/entgql/internal/todoplugin/ent/user/where.go +++ b/entgql/internal/todoplugin/ent/user/where.go @@ -106,6 +106,20 @@ func IDLTE(id int) predicate.User { }) } +// IDIsNil applies the IsNil predicate on the ID field. +func IDIsNil(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldID))) + }) +} + +// IDNotNil applies the NotNil predicate on the ID field. +func IDNotNil(id int) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldID))) + }) +} + // Username applies equality check predicate on the "username" field. It's identical to UsernameEQ. func Username(v string) predicate.User { return predicate.User(func(s *sql.Selector) { diff --git a/entgql/internal/todoplugin/ent/user_create.go b/entgql/internal/todoplugin/ent/user_create.go index 50c6e7850..feab95b10 100644 --- a/entgql/internal/todoplugin/ent/user_create.go +++ b/entgql/internal/todoplugin/ent/user_create.go @@ -59,6 +59,20 @@ func (uc *UserCreate) SetRole(r role.Role) *UserCreate { return uc } +// SetID sets the "id" field. +func (uc *UserCreate) SetID(i int) *UserCreate { + uc.mutation.SetID(i) + return uc +} + +// SetNillableID sets the "id" field if the given value is not nil. +func (uc *UserCreate) SetNillableID(i *int) *UserCreate { + if i != nil { + uc.SetID(*i) + } + return uc +} + // Mutation returns the UserMutation object of the builder. func (uc *UserCreate) Mutation() *UserMutation { return uc.mutation @@ -157,8 +171,10 @@ func (uc *UserCreate) sqlSave(ctx context.Context) (*User, error) { } return nil, err } - id := _spec.ID.Value.(int64) - _node.ID = int(id) + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int(id) + } return _node, nil } @@ -173,6 +189,10 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { }, } ) + if id, ok := uc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } if value, ok := uc.mutation.Username(); ok { _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ Type: field.TypeString, @@ -249,7 +269,7 @@ func (ucb *UserCreateBulk) Save(ctx context.Context) ([]*User, error) { } mutation.id = &nodes[i].ID mutation.done = true - if specs[i].ID.Value != nil { + if specs[i].ID.Value != nil && nodes[i].ID == 0 { id := specs[i].ID.Value.(int64) nodes[i].ID = int(id) } diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index 36eddfc2b..888ec0617 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -32,6 +32,8 @@ type ( graph *gen.Graph nodes []*gen.Type schema *ast.Schema + + relaySpec bool } // EntGQLPluginOption is a option for the EntGQL plugin @@ -47,6 +49,14 @@ var ( _ plugin.ConfigMutator = (*EntGQL)(nil) ) +// WithRelaySpecification adds the Relay specification to the schema +func WithRelaySpecification(relaySpec bool) EntGQLPluginOption { + return func(e *EntGQL) error { + e.relaySpec = relaySpec + return nil + } +} + // NewEntGQLPlugin creates a new EntGQL plugin func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLPluginOption) (*EntGQL, error) { nodes, err := entgql.FilterNodes(graph.Nodes) @@ -112,6 +122,10 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { } var interfaces []string + if e.relaySpec { + interfaces = append(interfaces, "Node") + } + types[name] = &ast.Definition{ Name: name, Kind: ast.Object, @@ -156,7 +170,7 @@ func (e *EntGQL) typeField(f *gen.Field, isID bool) ([]*ast.FieldDefinition, err return nil, nil } - ft, err := typeFromField(f, isID, ant.Type) + ft, err := e.typeFromField(f, isID, ant.Type) if err != nil { return nil, fmt.Errorf("field(%s): %w", f.Name, err) } @@ -178,20 +192,19 @@ func namedType(name string, nullable bool) *ast.Type { return ast.NonNullNamedType(name, nil) } -func typeFromField(f *gen.Field, idField bool, userDefinedType string) (*ast.Type, error) { +func (e *EntGQL) typeFromField(f *gen.Field, idField bool, userDefinedType string) (*ast.Type, error) { nillable := f.Nillable typ := f.Type.Type // TODO(giautm): Support custom scalar types // TODO(giautm): Support Edge Field - // TODO(giautm): Support nullable ID for non-relay // TODO(giautm): Support some built-in JSON types: Ints(), Floats(), Strings() scalar := f.Type.String() switch { case userDefinedType != "": return namedType(userDefinedType, nillable), nil case idField: - return namedType("ID", false), nil + return namedType("ID", !e.relaySpec && nillable), nil case typ.Float(): return namedType("Float", nillable), nil case typ.Integer(): diff --git a/entgql/plugin/plugin_config.go b/entgql/plugin/plugin_config.go index be014e1e1..f5fa30c59 100644 --- a/entgql/plugin/plugin_config.go +++ b/entgql/plugin/plugin_config.go @@ -20,8 +20,30 @@ import ( "github.com/99designs/gqlgen/codegen/config" ) +var ( + // RelayCursor is the name of the cursor type + RelayCursor = "Cursor" + // RelayNode is the name of the interface that all nodes implement + RelayNode = "Node" + // RelayPageInfo is the name of the PageInfo type + RelayPageInfo = "PageInfo" +) + // MutateConfig implements the ConfigMutator interface func (e *EntGQL) MutateConfig(cfg *config.Config) error { + if e.relaySpec { + if !cfg.Models.Exists(RelayPageInfo) { + cfg.Models.Add(RelayPageInfo, e.entGoType(RelayPageInfo)) + } + if !cfg.Models.Exists(RelayNode) { + // Bind to Noder interface + cfg.Models.Add(RelayNode, e.entGoType("Noder")) + } + if !cfg.Models.Exists(RelayCursor) { + cfg.Models.Add(RelayCursor, e.entGoType(RelayCursor)) + } + } + for _, node := range e.nodes { ant, err := decodeAnnotation(node.Annotations) if err != nil { diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go index 71520a28b..ef47cd466 100644 --- a/entgql/plugin/plugin_config_test.go +++ b/entgql/plugin/plugin_config_test.go @@ -117,3 +117,86 @@ func TestModifyConfig(t *testing.T) { } require.Equal(t, expected, cfg) } + +func TestModifyConfig_relay(t *testing.T) { + e, err := NewEntGQLPlugin(&gen.Graph{ + Config: &gen.Config{ + Package: "example.com", + IDType: &field.TypeInfo{ + Type: field.TypeInt, + }, + }, + Nodes: []*gen.Type{ + { + Name: "Todo", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + }, + { + Name: "User", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "Skip": true, + }, + }, + }, + { + Name: "Group", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, + }, + }, + { + Name: "GroupWithSort", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "OrderField": "NAME", + }, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, + }, + }, + }, + }, WithRelaySpecification(true)) + require.NoError(t, err) + cfg := config.DefaultConfig() + err = e.MutateConfig(cfg) + require.NoError(t, err) + expected := config.DefaultConfig() + expected.Models = map[string]config.TypeMapEntry{ + "Cursor": {Model: []string{"example.com.Cursor"}}, + "Group": {Model: []string{"example.com.Group"}}, + "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, + "Node": {Model: []string{"example.com.Noder"}}, + "PageInfo": {Model: []string{"example.com.PageInfo"}}, + "Todo": {Model: []string{"example.com.Todo"}}, + } + require.Equal(t, expected, cfg) +} diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go index 5c0ab5d52..f0b2938fc 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/plugin/plugin_test.go @@ -42,7 +42,7 @@ func TestEntGQL_buildTypes(t *testing.T) { count: Uint64! } type MasterUser { - id: ID! + id: ID username: String! age: Float! amount: Float! @@ -60,3 +60,41 @@ type Todo { Types: types, })) } + +func TestEntGQL_buildTypes_relay(t *testing.T) { + graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) + require.NoError(t, err) + plugin, err := NewEntGQLPlugin(graph, WithRelaySpecification(true)) + + require.NoError(t, err) + types, err := plugin.buildTypes() + require.NoError(t, err) + + require.Equal(t, `type Category implements Node { + id: ID! + text: String! + uuidA: UUID + status: CategoryStatus! + config: CategoryConfig! + duration: Duration! + count: Uint64! +} +type MasterUser implements Node { + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! +} +type Todo implements Node { + id: ID! + createdAt: Time! + visibilityStatus: VisibilityStatus! + status: Status! + priority: Int! + text: String! +} +`, printSchema(&ast.Schema{ + Types: types, + })) +} From 577c759bd6e7e0753ebc2f52f393c3b06e038c03 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Tue, 1 Mar 2022 22:33:15 +0000 Subject: [PATCH 08/23] fix: fixed lint --- entgql/plugin/plugin_config_test.go | 181 +++++++++------------------- 1 file changed, 59 insertions(+), 122 deletions(-) diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go index ef47cd466..61972610e 100644 --- a/entgql/plugin/plugin_config_test.go +++ b/entgql/plugin/plugin_config_test.go @@ -38,73 +38,75 @@ func TestModifyConfig_empty(t *testing.T) { require.Equal(t, expected, cfg) } -func TestModifyConfig(t *testing.T) { - e, err := NewEntGQLPlugin(&gen.Graph{ - Config: &gen.Config{ - Package: "example.com", - IDType: &field.TypeInfo{ - Type: field.TypeInt, - }, +var g = &gen.Graph{ + Config: &gen.Config{ + Package: "example.com", + IDType: &field.TypeInfo{ + Type: field.TypeInt, }, - Nodes: []*gen.Type{ - { - Name: "Todo", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - }, - { - Name: "User", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "Skip": true, - }, + }, + Nodes: []*gen.Type{ + { + Name: "Todo", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + }, + { + Name: "User", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "Skip": true, }, }, - { - Name: "Group", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "RelayConnection": true, - }, + }, + { + Name: "Group", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, }, }, - { - Name: "GroupWithSort", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "OrderField": "NAME", - }, - }, - }}, + }, + { + Name: "GroupWithSort", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, Annotations: map[string]interface{}{ annotationName: map[string]interface{}{ - "RelayConnection": true, + "OrderField": "NAME", }, }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, }, }, - }) + }, +} + +func TestModifyConfig(t *testing.T) { + e, err := NewEntGQLPlugin(g) require.NoError(t, err) cfg := config.DefaultConfig() err = e.MutateConfig(cfg) @@ -119,72 +121,7 @@ func TestModifyConfig(t *testing.T) { } func TestModifyConfig_relay(t *testing.T) { - e, err := NewEntGQLPlugin(&gen.Graph{ - Config: &gen.Config{ - Package: "example.com", - IDType: &field.TypeInfo{ - Type: field.TypeInt, - }, - }, - Nodes: []*gen.Type{ - { - Name: "Todo", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - }, - { - Name: "User", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "Skip": true, - }, - }, - }, - { - Name: "Group", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "RelayConnection": true, - }, - }, - }, - { - Name: "GroupWithSort", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "OrderField": "NAME", - }, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "RelayConnection": true, - }, - }, - }, - }, - }, WithRelaySpecification(true)) + e, err := NewEntGQLPlugin(g, WithRelaySpecification(true)) require.NoError(t, err) cfg := config.DefaultConfig() err = e.MutateConfig(cfg) From 2d7543a7098ce380534fcc9ee40fc034f94dc03c Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 11:00:05 +0000 Subject: [PATCH 09/23] feat(extension): support for custom GQL Type --- entgql/annotation.go | 15 + .../internal/todoplugin/ent/gql_pagination.go | 115 +- entgql/internal/todoplugin/generated.go | 1117 +++++++++++------ entgql/internal/todoplugin/todo.graphql | 13 +- entgql/internal/todoplugin/todo.resolvers.go | 22 +- entgql/template.go | 43 +- entgql/template/pagination.tmpl | 13 +- 7 files changed, 887 insertions(+), 451 deletions(-) diff --git a/entgql/annotation.go b/entgql/annotation.go index 53b4e751c..a82abc7ce 100644 --- a/entgql/annotation.go +++ b/entgql/annotation.go @@ -17,6 +17,7 @@ package entgql import ( "encoding/json" + "entgo.io/ent/entc/gen" "entgo.io/ent/schema" ) @@ -125,6 +126,20 @@ func (a *Annotation) Decode(annotation interface{}) error { return json.Unmarshal(buf, a) } +// DecodeAnnotation decodes the annotation from the schema. +func DecodeAnnotation(annotations gen.Annotations) (*Annotation, error) { + ant := &Annotation{} + if annotations == nil || annotations[ant.Name()] == nil { + return ant, nil + } + + err := ant.Decode(annotations[ant.Name()]) + if err != nil { + return nil, err + } + return ant, nil +} + var ( _ schema.Annotation = (*Annotation)(nil) _ schema.Merger = (*Annotation)(nil) diff --git a/entgql/internal/todoplugin/ent/gql_pagination.go b/entgql/internal/todoplugin/ent/gql_pagination.go index 803221416..a612fc98f 100644 --- a/entgql/internal/todoplugin/ent/gql_pagination.go +++ b/entgql/internal/todoplugin/ent/gql_pagination.go @@ -858,43 +858,46 @@ func (t *Todo) ToEdge(order *TodoOrder) *TodoEdge { } } -// UserEdge is the edge representation of User. -type UserEdge struct { - Node *User `json:"node"` - Cursor Cursor `json:"cursor"` +// MasterUser is the type alias for User. +type MasterUser = User + +// MasterUserEdge is the edge representation of MasterUser. +type MasterUserEdge struct { + Node *MasterUser `json:"node"` + Cursor Cursor `json:"cursor"` } -// UserConnection is the connection containing edges to User. -type UserConnection struct { - Edges []*UserEdge `json:"edges"` - PageInfo PageInfo `json:"pageInfo"` - TotalCount int `json:"totalCount"` +// MasterUserConnection is the connection containing edges to MasterUser. +type MasterUserConnection struct { + Edges []*MasterUserEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` } -// UserPaginateOption enables pagination customization. -type UserPaginateOption func(*userPager) error +// MasterUserPaginateOption enables pagination customization. +type MasterUserPaginateOption func(*masterUserPager) error -// WithUserOrder configures pagination ordering. -func WithUserOrder(order *UserOrder) UserPaginateOption { +// WithMasterUserOrder configures pagination ordering. +func WithMasterUserOrder(order *MasterUserOrder) MasterUserPaginateOption { if order == nil { - order = DefaultUserOrder + order = DefaultMasterUserOrder } o := *order - return func(pager *userPager) error { + return func(pager *masterUserPager) error { if err := o.Direction.Validate(); err != nil { return err } if o.Field == nil { - o.Field = DefaultUserOrder.Field + o.Field = DefaultMasterUserOrder.Field } pager.order = &o return nil } } -// WithUserFilter configures pagination filter. -func WithUserFilter(filter func(*UserQuery) (*UserQuery, error)) UserPaginateOption { - return func(pager *userPager) error { +// WithMasterUserFilter configures pagination filter. +func WithMasterUserFilter(filter func(*UserQuery) (*UserQuery, error)) MasterUserPaginateOption { + return func(pager *masterUserPager) error { if filter == nil { return errors.New("UserQuery filter cannot be nil") } @@ -903,66 +906,66 @@ func WithUserFilter(filter func(*UserQuery) (*UserQuery, error)) UserPaginateOpt } } -type userPager struct { - order *UserOrder +type masterUserPager struct { + order *MasterUserOrder filter func(*UserQuery) (*UserQuery, error) } -func newUserPager(opts []UserPaginateOption) (*userPager, error) { - pager := &userPager{} +func newMasterUserPager(opts []MasterUserPaginateOption) (*masterUserPager, error) { + pager := &masterUserPager{} for _, opt := range opts { if err := opt(pager); err != nil { return nil, err } } if pager.order == nil { - pager.order = DefaultUserOrder + pager.order = DefaultMasterUserOrder } return pager, nil } -func (p *userPager) applyFilter(query *UserQuery) (*UserQuery, error) { +func (p *masterUserPager) applyFilter(query *UserQuery) (*UserQuery, error) { if p.filter != nil { return p.filter(query) } return query, nil } -func (p *userPager) toCursor(u *User) Cursor { +func (p *masterUserPager) toCursor(u *MasterUser) Cursor { return p.order.Field.toCursor(u) } -func (p *userPager) applyCursors(query *UserQuery, after, before *Cursor) *UserQuery { +func (p *masterUserPager) applyCursors(query *UserQuery, after, before *Cursor) *UserQuery { for _, predicate := range cursorsToPredicates( p.order.Direction, after, before, - p.order.Field.field, DefaultUserOrder.Field.field, + p.order.Field.field, DefaultMasterUserOrder.Field.field, ) { query = query.Where(predicate) } return query } -func (p *userPager) applyOrder(query *UserQuery, reverse bool) *UserQuery { +func (p *masterUserPager) applyOrder(query *UserQuery, reverse bool) *UserQuery { direction := p.order.Direction if reverse { direction = direction.reverse() } query = query.Order(direction.orderFunc(p.order.Field.field)) - if p.order.Field != DefaultUserOrder.Field { - query = query.Order(direction.orderFunc(DefaultUserOrder.Field.field)) + if p.order.Field != DefaultMasterUserOrder.Field { + query = query.Order(direction.orderFunc(DefaultMasterUserOrder.Field.field)) } return query } -// Paginate executes the query and returns a relay based cursor connection to User. +// Paginate executes the query and returns a relay based cursor connection to MasterUser. func (u *UserQuery) Paginate( ctx context.Context, after *Cursor, first *int, - before *Cursor, last *int, opts ...UserPaginateOption, -) (*UserConnection, error) { + before *Cursor, last *int, opts ...MasterUserPaginateOption, +) (*MasterUserConnection, error) { if err := validateFirstLast(first, last); err != nil { return nil, err } - pager, err := newUserPager(opts) + pager, err := newMasterUserPager(opts) if err != nil { return nil, err } @@ -971,7 +974,7 @@ func (u *UserQuery) Paginate( return nil, err } - conn := &UserConnection{Edges: []*UserEdge{}} + conn := &MasterUserConnection{Edges: []*MasterUserEdge{}} if !hasCollectedField(ctx, edgesField) || first != nil && *first == 0 || last != nil && *last == 0 { if hasCollectedField(ctx, totalCountField) || hasCollectedField(ctx, pageInfoField) { @@ -1021,22 +1024,22 @@ func (u *UserQuery) Paginate( nodes = nodes[:len(nodes)-1] } - var nodeAt func(int) *User + var nodeAt func(int) *MasterUser if last != nil { n := len(nodes) - 1 - nodeAt = func(i int) *User { + nodeAt = func(i int) *MasterUser { return nodes[n-i] } } else { - nodeAt = func(i int) *User { + nodeAt = func(i int) *MasterUser { return nodes[i] } } - conn.Edges = make([]*UserEdge, len(nodes)) + conn.Edges = make([]*MasterUserEdge, len(nodes)) for i := range nodes { node := nodeAt(i) - conn.Edges[i] = &UserEdge{ + conn.Edges[i] = &MasterUserEdge{ Node: node, Cursor: pager.toCursor(node), } @@ -1051,35 +1054,35 @@ func (u *UserQuery) Paginate( return conn, nil } -// UserOrderField defines the ordering field of User. -type UserOrderField struct { +// MasterUserOrderField defines the ordering field of User. +type MasterUserOrderField struct { field string - toCursor func(*User) Cursor + toCursor func(*MasterUser) Cursor } -// UserOrder defines the ordering of User. -type UserOrder struct { - Direction OrderDirection `json:"direction"` - Field *UserOrderField `json:"field"` +// MasterUserOrder defines the ordering of User. +type MasterUserOrder struct { + Direction OrderDirection `json:"direction"` + Field *MasterUserOrderField `json:"field"` } -// DefaultUserOrder is the default ordering of User. -var DefaultUserOrder = &UserOrder{ +// DefaultMasterUserOrder is the default ordering of User. +var DefaultMasterUserOrder = &MasterUserOrder{ Direction: OrderDirectionAsc, - Field: &UserOrderField{ + Field: &MasterUserOrderField{ field: user.FieldID, - toCursor: func(u *User) Cursor { + toCursor: func(u *MasterUser) Cursor { return Cursor{ID: u.ID} }, }, } -// ToEdge converts User into UserEdge. -func (u *User) ToEdge(order *UserOrder) *UserEdge { +// ToEdge converts MasterUser into MasterUserEdge. +func (u *MasterUser) ToEdge(order *MasterUserOrder) *MasterUserEdge { if order == nil { - order = DefaultUserOrder + order = DefaultMasterUserOrder } - return &UserEdge{ + return &MasterUserEdge{ Node: u, Cursor: order.Field.toCursor(u), } diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go index 29071da1d..52702a930 100644 --- a/entgql/internal/todoplugin/generated.go +++ b/entgql/internal/todoplugin/generated.go @@ -44,10 +44,10 @@ type Config struct { } type ResolverRoot interface { + MasterUser() MasterUserResolver Mutation() MutationResolver Query() QueryResolver Todo() TodoResolver - User() UserResolver } type DirectiveRoot struct { @@ -69,6 +69,25 @@ type ComplexityRoot struct { MaxMembers func(childComplexity int) int } + MasterUser struct { + Age func(childComplexity int) int + Amount func(childComplexity int) int + ID func(childComplexity int) int + Role func(childComplexity int) int + Username func(childComplexity int) int + } + + MasterUserConnection struct { + Edges func(childComplexity int) int + PageInfo func(childComplexity int) int + TotalCount func(childComplexity int) int + } + + MasterUserEdge struct { + Cursor func(childComplexity int) int + Node func(childComplexity int) int + } + Mutation struct { ClearTodos func(childComplexity int) int CreateTodo func(childComplexity int, todo TodoInput) int @@ -108,16 +127,12 @@ type ComplexityRoot struct { Cursor func(childComplexity int) int Node func(childComplexity int) int } - - User struct { - Age func(childComplexity int) int - Amount func(childComplexity int) int - ID func(childComplexity int) int - Role func(childComplexity int) int - Username func(childComplexity int) int - } } +type MasterUserResolver interface { + Age(ctx context.Context, obj *ent.User) (float64, error) + Amount(ctx context.Context, obj *ent.User) (float64, error) +} type MutationResolver interface { CreateTodo(ctx context.Context, todo TodoInput) (*ent.Todo, error) ClearTodos(ctx context.Context) (int, error) @@ -130,10 +145,6 @@ type QueryResolver interface { type TodoResolver interface { Category(ctx context.Context, obj *ent.Todo) (*ent.Category, error) } -type UserResolver interface { - Age(ctx context.Context, obj *ent.User) (float64, error) - Amount(ctx context.Context, obj *ent.User) (float64, error) -} type executableSchema struct { resolvers ResolverRoot @@ -206,6 +217,76 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.CategoryConfig.MaxMembers(childComplexity), true + case "MasterUser.age": + if e.complexity.MasterUser.Age == nil { + break + } + + return e.complexity.MasterUser.Age(childComplexity), true + + case "MasterUser.amount": + if e.complexity.MasterUser.Amount == nil { + break + } + + return e.complexity.MasterUser.Amount(childComplexity), true + + case "MasterUser.id": + if e.complexity.MasterUser.ID == nil { + break + } + + return e.complexity.MasterUser.ID(childComplexity), true + + case "MasterUser.role": + if e.complexity.MasterUser.Role == nil { + break + } + + return e.complexity.MasterUser.Role(childComplexity), true + + case "MasterUser.username": + if e.complexity.MasterUser.Username == nil { + break + } + + return e.complexity.MasterUser.Username(childComplexity), true + + case "MasterUserConnection.edges": + if e.complexity.MasterUserConnection.Edges == nil { + break + } + + return e.complexity.MasterUserConnection.Edges(childComplexity), true + + case "MasterUserConnection.pageInfo": + if e.complexity.MasterUserConnection.PageInfo == nil { + break + } + + return e.complexity.MasterUserConnection.PageInfo(childComplexity), true + + case "MasterUserConnection.totalCount": + if e.complexity.MasterUserConnection.TotalCount == nil { + break + } + + return e.complexity.MasterUserConnection.TotalCount(childComplexity), true + + case "MasterUserEdge.cursor": + if e.complexity.MasterUserEdge.Cursor == nil { + break + } + + return e.complexity.MasterUserEdge.Cursor(childComplexity), true + + case "MasterUserEdge.node": + if e.complexity.MasterUserEdge.Node == nil { + break + } + + return e.complexity.MasterUserEdge.Node(childComplexity), true + case "Mutation.clearTodos": if e.complexity.Mutation.ClearTodos == nil { break @@ -380,41 +461,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.TodoEdge.Node(childComplexity), true - case "User.age": - if e.complexity.User.Age == nil { - break - } - - return e.complexity.User.Age(childComplexity), true - - case "User.amount": - if e.complexity.User.Amount == nil { - break - } - - return e.complexity.User.Amount(childComplexity), true - - case "User.id": - if e.complexity.User.ID == nil { - break - } - - return e.complexity.User.ID(childComplexity), true - - case "User.role": - if e.complexity.User.Role == nil { - break - } - - return e.complexity.User.Role(childComplexity), true - - case "User.username": - if e.complexity.User.Username == nil { - break - } - - return e.complexity.User.Username(childComplexity), true - } return 0, false } @@ -584,7 +630,7 @@ enum Role { UNKNOWN } -type User implements Node { +type MasterUser implements Node { id: ID! username: String! age: Float! @@ -592,6 +638,17 @@ type User implements Node { role: Role! } +type MasterUserConnection { + totalCount: Int! + pageInfo: PageInfo! + edges: [MasterUserEdge] +} + +type MasterUserEdge { + node: MasterUser + cursor: Cursor! +} + type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! @@ -1078,7 +1135,7 @@ func (ec *executionContext) _CategoryConfig_maxMembers(ctx context.Context, fiel return ec.marshalOInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _Mutation_createTodo(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUser_id(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1086,24 +1143,52 @@ func (ec *executionContext) _Mutation_createTodo(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "Mutation", + Object: "MasterUser", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Mutation_createTodo_args(ctx, rawArgs) + 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 } - fc.Args = args + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(int) + fc.Result = res + return ec.marshalNID2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _MasterUser_username(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MasterUser", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().CreateTodo(rctx, args["todo"].(TodoInput)) + return obj.Username, nil }) if err != nil { ec.Error(ctx, err) @@ -1115,12 +1200,12 @@ func (ec *executionContext) _Mutation_createTodo(ctx context.Context, field grap } return graphql.Null } - res := resTmp.(*ent.Todo) + res := resTmp.(string) fc.Result = res - return ec.marshalNTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Mutation_clearTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUser_age(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1128,7 +1213,7 @@ func (ec *executionContext) _Mutation_clearTodos(ctx context.Context, field grap } }() fc := &graphql.FieldContext{ - Object: "Mutation", + Object: "MasterUser", Field: field, Args: nil, IsMethod: true, @@ -1138,7 +1223,7 @@ func (ec *executionContext) _Mutation_clearTodos(ctx context.Context, field grap ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().ClearTodos(rctx) + return ec.resolvers.MasterUser().Age(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -1150,12 +1235,12 @@ func (ec *executionContext) _Mutation_clearTodos(ctx context.Context, field grap } return graphql.Null } - res := resTmp.(int) + res := resTmp.(float64) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNFloat2float64(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUser_amount(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1163,7 +1248,42 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "MasterUser", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.MasterUser().Amount(rctx, obj) + }) + 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.(float64) + fc.Result = res + return ec.marshalNFloat2float64(ctx, field.Selections, res) +} + +func (ec *executionContext) _MasterUser_role(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MasterUser", Field: field, Args: nil, IsMethod: false, @@ -1173,7 +1293,7 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.HasNextPage, nil + return obj.Role, nil }) if err != nil { ec.Error(ctx, err) @@ -1185,12 +1305,12 @@ func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(role.Role) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNRole2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋroleᚐRole(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUserConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1198,7 +1318,7 @@ func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "MasterUserConnection", Field: field, Args: nil, IsMethod: false, @@ -1208,7 +1328,7 @@ func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.HasPreviousPage, nil + return obj.TotalCount, nil }) if err != nil { ec.Error(ctx, err) @@ -1220,12 +1340,12 @@ func (ec *executionContext) _PageInfo_hasPreviousPage(ctx context.Context, field } return graphql.Null } - res := resTmp.(bool) + res := resTmp.(int) fc.Result = res - return ec.marshalNBoolean2bool(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUserConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1233,7 +1353,7 @@ func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "MasterUserConnection", Field: field, Args: nil, IsMethod: false, @@ -1243,21 +1363,24 @@ func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.StartCursor, nil + return obj.PageInfo, 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.(*ent.Cursor) + res := resTmp.(ent.PageInfo) fc.Result = res - return ec.marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) + return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUserConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1265,7 +1388,7 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph } }() fc := &graphql.FieldContext{ - Object: "PageInfo", + Object: "MasterUserConnection", Field: field, Args: nil, IsMethod: false, @@ -1275,7 +1398,7 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.EndCursor, nil + return obj.Edges, nil }) if err != nil { ec.Error(ctx, err) @@ -1284,12 +1407,12 @@ func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graph if resTmp == nil { return graphql.Null } - res := resTmp.(*ent.Cursor) + res := resTmp.([]*ent.MasterUserEdge) fc.Result = res - return ec.marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) + return ec.marshalOMasterUserEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐMasterUserEdge(ctx, field.Selections, res) } -func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUserEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1297,38 +1420,66 @@ func (ec *executionContext) _Query_node(ctx context.Context, field graphql.Colle } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "MasterUserEdge", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_node_args(ctx, rawArgs) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Node, nil + }) if err != nil { ec.Error(ctx, err) return graphql.Null } - fc.Args = args + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.User) + fc.Result = res + return ec.marshalOMasterUser2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐUser(ctx, field.Selections, res) +} + +func (ec *executionContext) _MasterUserEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserEdge) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "MasterUserEdge", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Node(rctx, args["id"].(int)) + return obj.Cursor, 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.(ent.Noder) + res := resTmp.(ent.Cursor) fc.Result = res - return ec.marshalONode2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, field.Selections, res) + return ec.marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Mutation_createTodo(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1336,7 +1487,7 @@ func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "Mutation", Field: field, Args: nil, IsMethod: true, @@ -1345,7 +1496,7 @@ func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.Coll ctx = graphql.WithFieldContext(ctx, fc) rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_nodes_args(ctx, rawArgs) + args, err := ec.field_Mutation_createTodo_args(ctx, rawArgs) if err != nil { ec.Error(ctx, err) return graphql.Null @@ -1353,7 +1504,7 @@ func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.Coll fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Nodes(rctx, args["ids"].([]int)) + return ec.resolvers.Mutation().CreateTodo(rctx, args["todo"].(TodoInput)) }) if err != nil { ec.Error(ctx, err) @@ -1365,12 +1516,12 @@ func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.([]ent.Noder) + res := resTmp.(*ent.Todo) fc.Result = res - return ec.marshalNNode2ᚕentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, field.Selections, res) + return ec.marshalNTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) } -func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _Mutation_clearTodos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1378,7 +1529,7 @@ func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "Mutation", Field: field, Args: nil, IsMethod: true, @@ -1386,30 +1537,26 @@ func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.Coll } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query_todos_args(ctx, rawArgs) - if err != nil { - ec.Error(ctx, err) - return graphql.Null - } - fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Todos(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.TodoOrder)) + return ec.resolvers.Mutation().ClearTodos(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.(*ent.TodoConnection) + res := resTmp.(int) fc.Result = res - return ec.marshalOTodoConnection2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoConnection(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_hasNextPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1417,38 +1564,69 @@ func (ec *executionContext) _Query___type(ctx context.Context, field graphql.Col } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "PageInfo", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) - rawArgs := field.ArgumentMap(ec.Variables) - args, err := ec.field_Query___type_args(ctx, rawArgs) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.HasNextPage, nil + }) if err != nil { ec.Error(ctx, err) return graphql.Null } - fc.Args = args + 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) _PageInfo_hasPreviousPage(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.introspectType(args["name"].(string)) + return obj.HasPreviousPage, 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) + res := resTmp.(bool) fc.Result = res - return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_startCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1456,17 +1634,17 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "Query", + Object: "PageInfo", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.introspectSchema() + return obj.StartCursor, nil }) if err != nil { ec.Error(ctx, err) @@ -1475,12 +1653,12 @@ func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.C if resTmp == nil { return graphql.Null } - res := resTmp.(*introspection.Schema) + res := resTmp.(*ent.Cursor) fc.Result = res - return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) + return ec.marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_id(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _PageInfo_endCursor(ctx context.Context, field graphql.CollectedField, obj *ent.PageInfo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1488,7 +1666,7 @@ func (ec *executionContext) _Todo_id(ctx context.Context, field graphql.Collecte } }() fc := &graphql.FieldContext{ - Object: "Todo", + Object: "PageInfo", Field: field, Args: nil, IsMethod: false, @@ -1498,24 +1676,21 @@ func (ec *executionContext) _Todo_id(ctx context.Context, field graphql.Collecte ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID, nil + return obj.EndCursor, 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.(int) + res := resTmp.(*ent.Cursor) fc.Result = res - return ec.marshalNID2int(ctx, field.Selections, res) + return ec.marshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_node(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1523,17 +1698,24 @@ func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.C } }() fc := &graphql.FieldContext{ - Object: "Todo", + Object: "Query", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_node_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.CreatedAt, nil + return ec.resolvers.Query().Node(rctx, args["id"].(int)) }) if err != nil { ec.Error(ctx, err) @@ -1542,12 +1724,12 @@ func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.C if resTmp == nil { return graphql.Null } - res := resTmp.(time.Time) + res := resTmp.(ent.Noder) fc.Result = res - return ec.marshalOTime2timeᚐTime(ctx, field.Selections, res) + return ec.marshalONode2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_status(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_nodes(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1555,17 +1737,24 @@ func (ec *executionContext) _Todo_status(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "Todo", + Object: "Query", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_nodes_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Status, nil + return ec.resolvers.Query().Nodes(rctx, args["ids"].([]int)) }) if err != nil { ec.Error(ctx, err) @@ -1577,12 +1766,12 @@ func (ec *executionContext) _Todo_status(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(todo.Status) + res := resTmp.([]ent.Noder) fc.Result = res - return ec.marshalNStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐStatus(ctx, field.Selections, res) + return ec.marshalNNode2ᚕentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_priority(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1590,34 +1779,77 @@ func (ec *executionContext) _Todo_priority(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "Todo", + Object: "Query", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_todos_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Priority, nil + return ec.resolvers.Query().Todos(rctx, args["after"].(*ent.Cursor), args["first"].(*int), args["before"].(*ent.Cursor), args["last"].(*int), args["orderBy"].(*ent.TodoOrder)) }) 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.(*ent.TodoConnection) + fc.Result = res + return ec.marshalOTodoConnection2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoConnection(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query___type_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) return graphql.Null } - res := resTmp.(int) + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.introspectType(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.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalO__Type2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐType(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_text(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Query___schema(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1625,34 +1857,31 @@ func (ec *executionContext) _Todo_text(ctx context.Context, field graphql.Collec } }() fc := &graphql.FieldContext{ - Object: "Todo", + Object: "Query", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Text, nil + return ec.introspectSchema() }) 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) + res := resTmp.(*introspection.Schema) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalO__Schema2ᚖgithubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐSchema(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_id(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1663,28 +1892,31 @@ func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.Coll Object: "Todo", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Parent(ctx) + 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.(*ent.Todo) + res := resTmp.(int) fc.Result = res - return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1695,14 +1927,14 @@ func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.Co Object: "Todo", Field: field, Args: nil, - IsMethod: true, + IsMethod: false, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Children(ctx) + return obj.CreatedAt, nil }) if err != nil { ec.Error(ctx, err) @@ -1711,12 +1943,12 @@ func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.Co if resTmp == nil { return graphql.Null } - res := resTmp.([]*ent.Todo) + res := resTmp.(time.Time) fc.Result = res - return ec.marshalOTodo2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoᚄ(ctx, field.Selections, res) + return ec.marshalOTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_status(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1727,28 +1959,31 @@ func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.Co Object: "Todo", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Todo().Category(rctx, obj) + return obj.Status, 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.(*ent.Category) + res := resTmp.(todo.Status) fc.Result = res - return ec.marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx, field.Selections, res) + return ec.marshalNStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐStatus(ctx, field.Selections, res) } -func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_priority(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1756,7 +1991,7 @@ func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, fiel } }() fc := &graphql.FieldContext{ - Object: "TodoConnection", + Object: "Todo", Field: field, Args: nil, IsMethod: false, @@ -1766,7 +2001,7 @@ func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalCount, nil + return obj.Priority, nil }) if err != nil { ec.Error(ctx, err) @@ -1783,7 +2018,7 @@ func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, fiel return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_text(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1791,7 +2026,7 @@ func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field } }() fc := &graphql.FieldContext{ - Object: "TodoConnection", + Object: "Todo", Field: field, Args: nil, IsMethod: false, @@ -1801,7 +2036,7 @@ func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PageInfo, nil + return obj.Text, nil }) if err != nil { ec.Error(ctx, err) @@ -1813,12 +2048,12 @@ func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field } return graphql.Null } - res := resTmp.(ent.PageInfo) + res := resTmp.(string) fc.Result = res - return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1826,17 +2061,17 @@ func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field gra } }() fc := &graphql.FieldContext{ - Object: "TodoConnection", + Object: "Todo", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edges, nil + return obj.Parent(ctx) }) if err != nil { ec.Error(ctx, err) @@ -1845,12 +2080,12 @@ func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field gra if resTmp == nil { return graphql.Null } - res := resTmp.([]*ent.TodoEdge) + res := resTmp.(*ent.Todo) fc.Result = res - return ec.marshalOTodoEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx, field.Selections, res) + return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) } -func (ec *executionContext) _TodoEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1858,17 +2093,17 @@ func (ec *executionContext) _TodoEdge_node(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "TodoEdge", + Object: "Todo", Field: field, Args: nil, - IsMethod: false, + IsMethod: true, IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Node, nil + return obj.Children(ctx) }) if err != nil { ec.Error(ctx, err) @@ -1877,12 +2112,12 @@ func (ec *executionContext) _TodoEdge_node(ctx context.Context, field graphql.Co if resTmp == nil { return graphql.Null } - res := resTmp.(*ent.Todo) + res := resTmp.([]*ent.Todo) fc.Result = res - return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) + return ec.marshalOTodo2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _TodoEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1890,34 +2125,31 @@ func (ec *executionContext) _TodoEdge_cursor(ctx context.Context, field graphql. } }() fc := &graphql.FieldContext{ - Object: "TodoEdge", + Object: "Todo", Field: field, Args: nil, - IsMethod: false, - IsResolver: false, + IsMethod: true, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Cursor, nil + return ec.resolvers.Todo().Category(rctx, obj) }) 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.(ent.Cursor) + res := resTmp.(*ent.Category) fc.Result = res - return ec.marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) + return ec.marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx, field.Selections, res) } -func (ec *executionContext) _User_id(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1925,7 +2157,7 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte } }() fc := &graphql.FieldContext{ - Object: "User", + Object: "TodoConnection", Field: field, Args: nil, IsMethod: false, @@ -1935,7 +2167,7 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ID, nil + return obj.TotalCount, nil }) if err != nil { ec.Error(ctx, err) @@ -1949,10 +2181,10 @@ func (ec *executionContext) _User_id(ctx context.Context, field graphql.Collecte } res := resTmp.(int) fc.Result = res - return ec.marshalNID2int(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) _User_username(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1960,7 +2192,7 @@ func (ec *executionContext) _User_username(ctx context.Context, field graphql.Co } }() fc := &graphql.FieldContext{ - Object: "User", + Object: "TodoConnection", Field: field, Args: nil, IsMethod: false, @@ -1970,7 +2202,7 @@ func (ec *executionContext) _User_username(ctx context.Context, field graphql.Co ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Username, nil + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -1982,12 +2214,12 @@ func (ec *executionContext) _User_username(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.(string) + res := resTmp.(ent.PageInfo) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _User_age(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1995,34 +2227,31 @@ func (ec *executionContext) _User_age(ctx context.Context, field graphql.Collect } }() fc := &graphql.FieldContext{ - Object: "User", + Object: "TodoConnection", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.User().Age(rctx, obj) + return obj.Edges, 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.(float64) + res := resTmp.([]*ent.TodoEdge) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalOTodoEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx, field.Selections, res) } -func (ec *executionContext) _User_amount(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2030,34 +2259,31 @@ func (ec *executionContext) _User_amount(ctx context.Context, field graphql.Coll } }() fc := &graphql.FieldContext{ - Object: "User", + Object: "TodoEdge", Field: field, Args: nil, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.User().Amount(rctx, obj) + return obj.Node, 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.(float64) + res := resTmp.(*ent.Todo) fc.Result = res - return ec.marshalNFloat2float64(ctx, field.Selections, res) + return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) } -func (ec *executionContext) _User_role(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2065,7 +2291,7 @@ func (ec *executionContext) _User_role(ctx context.Context, field graphql.Collec } }() fc := &graphql.FieldContext{ - Object: "User", + Object: "TodoEdge", Field: field, Args: nil, IsMethod: false, @@ -2075,7 +2301,7 @@ func (ec *executionContext) _User_role(ctx context.Context, field graphql.Collec ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Role, nil + return obj.Cursor, nil }) if err != nil { ec.Error(ctx, err) @@ -2087,9 +2313,9 @@ func (ec *executionContext) _User_role(ctx context.Context, field graphql.Collec } return graphql.Null } - res := resTmp.(role.Role) + res := resTmp.(ent.Cursor) fc.Result = res - return ec.marshalNRole2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋroleᚐRole(ctx, field.Selections, res) + return ec.marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) } func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { @@ -3356,66 +3582,236 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj if obj == nil { return graphql.Null } - return ec._User(ctx, sel, obj) - default: - panic(fmt.Errorf("unexpected type %T", obj)) + return ec._MasterUser(ctx, sel, obj) + default: + panic(fmt.Errorf("unexpected type %T", obj)) + } +} + +// endregion ************************** interface.gotpl *************************** + +// region **************************** object.gotpl **************************** + +var categoryImplementors = []string{"Category", "Node"} + +func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, obj *ent.Category) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, categoryImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("Category") + case "id": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_id(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "text": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_text(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "uuidA": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_uuidA(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "status": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_status(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "config": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_config(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "duration": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_duration(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "count": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Category_count(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var categoryConfigImplementors = []string{"CategoryConfig"} + +func (ec *executionContext) _CategoryConfig(ctx context.Context, sel ast.SelectionSet, obj *schematype.CategoryConfig) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, categoryConfigImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("CategoryConfig") + case "maxMembers": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryConfig_maxMembers(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null } + return out } -// endregion ************************** interface.gotpl *************************** - -// region **************************** object.gotpl **************************** - -var categoryImplementors = []string{"Category", "Node"} +var masterUserImplementors = []string{"MasterUser", "Node"} -func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, obj *ent.Category) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, categoryImplementors) +func (ec *executionContext) _MasterUser(ctx context.Context, sel ast.SelectionSet, obj *ent.User) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, masterUserImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("Category") + out.Values[i] = graphql.MarshalString("MasterUser") case "id": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_id(ctx, field, obj) + return ec._MasterUser_id(ctx, field, obj) } out.Values[i] = innerFunc(ctx) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } - case "text": + case "username": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_text(ctx, field, obj) + return ec._MasterUser_username(ctx, field, obj) } out.Values[i] = innerFunc(ctx) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } - case "uuidA": + case "age": + field := field + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_uuidA(ctx, field, obj) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._MasterUser_age(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res } - out.Values[i] = innerFunc(ctx) + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "amount": + field := field - case "status": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_status(ctx, field, obj) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._MasterUser_amount(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + } + + out.Concurrently(i, func() graphql.Marshaler { + return innerFunc(ctx) + + }) + case "role": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._MasterUser_role(ctx, field, obj) } out.Values[i] = innerFunc(ctx) if out.Values[i] == graphql.Null { - invalids++ + atomic.AddUint32(&invalids, 1) } - case "config": + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var masterUserConnectionImplementors = []string{"MasterUserConnection"} + +func (ec *executionContext) _MasterUserConnection(ctx context.Context, sel ast.SelectionSet, obj *ent.MasterUserConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, masterUserConnectionImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("MasterUserConnection") + case "totalCount": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_config(ctx, field, obj) + return ec._MasterUserConnection_totalCount(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -3423,9 +3819,9 @@ func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { invalids++ } - case "duration": + case "pageInfo": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_duration(ctx, field, obj) + return ec._MasterUserConnection_pageInfo(ctx, field, obj) } out.Values[i] = innerFunc(ctx) @@ -3433,16 +3829,13 @@ func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, if out.Values[i] == graphql.Null { invalids++ } - case "count": + case "edges": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._Category_count(ctx, field, obj) + return ec._MasterUserConnection_edges(ctx, field, obj) } out.Values[i] = innerFunc(ctx) - if out.Values[i] == graphql.Null { - invalids++ - } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -3454,23 +3847,33 @@ func (ec *executionContext) _Category(ctx context.Context, sel ast.SelectionSet, return out } -var categoryConfigImplementors = []string{"CategoryConfig"} +var masterUserEdgeImplementors = []string{"MasterUserEdge"} -func (ec *executionContext) _CategoryConfig(ctx context.Context, sel ast.SelectionSet, obj *schematype.CategoryConfig) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, categoryConfigImplementors) +func (ec *executionContext) _MasterUserEdge(ctx context.Context, sel ast.SelectionSet, obj *ent.MasterUserEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, masterUserEdgeImplementors) out := graphql.NewFieldSet(fields) var invalids uint32 for i, field := range fields { switch field.Name { case "__typename": - out.Values[i] = graphql.MarshalString("CategoryConfig") - case "maxMembers": + out.Values[i] = graphql.MarshalString("MasterUserEdge") + case "node": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._CategoryConfig_maxMembers(ctx, field, obj) + return ec._MasterUserEdge_node(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "cursor": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._MasterUserEdge_cursor(ctx, field, obj) } out.Values[i] = innerFunc(ctx) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -3899,97 +4302,6 @@ func (ec *executionContext) _TodoEdge(ctx context.Context, sel ast.SelectionSet, return out } -var userImplementors = []string{"User", "Node"} - -func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj *ent.User) graphql.Marshaler { - fields := graphql.CollectFields(ec.OperationContext, sel, userImplementors) - out := graphql.NewFieldSet(fields) - var invalids uint32 - for i, field := range fields { - switch field.Name { - case "__typename": - out.Values[i] = graphql.MarshalString("User") - case "id": - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._User_id(ctx, field, obj) - } - - out.Values[i] = innerFunc(ctx) - - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "username": - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._User_username(ctx, field, obj) - } - - out.Values[i] = innerFunc(ctx) - - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - case "age": - field := field - - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._User_age(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - } - - out.Concurrently(i, func() graphql.Marshaler { - return innerFunc(ctx) - - }) - case "amount": - field := field - - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - } - }() - res = ec._User_amount(ctx, field, obj) - if res == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - return res - } - - out.Concurrently(i, func() graphql.Marshaler { - return innerFunc(ctx) - - }) - case "role": - innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._User_role(ctx, field, obj) - } - - out.Values[i] = innerFunc(ctx) - - if out.Values[i] == graphql.Null { - atomic.AddUint32(&invalids, 1) - } - default: - panic("unknown field " + strconv.Quote(field.Name)) - } - } - out.Dispatch() - if invalids > 0 { - return graphql.Null - } - return out -} - var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { @@ -5001,6 +5313,61 @@ func (ec *executionContext) marshalOInt2ᚖint(ctx context.Context, sel ast.Sele return res } +func (ec *executionContext) marshalOMasterUser2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐUser(ctx context.Context, sel ast.SelectionSet, v *ent.User) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._MasterUser(ctx, sel, v) +} + +func (ec *executionContext) marshalOMasterUserEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐMasterUserEdge(ctx context.Context, sel ast.SelectionSet, v []*ent.MasterUserEdge) 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.marshalOMasterUserEdge2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐMasterUserEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) marshalOMasterUserEdge2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐMasterUserEdge(ctx context.Context, sel ast.SelectionSet, v *ent.MasterUserEdge) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._MasterUserEdge(ctx, sel, v) +} + func (ec *executionContext) marshalONode2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐNoder(ctx context.Context, sel ast.SelectionSet, v ent.Noder) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql index 11c677eb2..71c68c449 100644 --- a/entgql/internal/todoplugin/todo.graphql +++ b/entgql/internal/todoplugin/todo.graphql @@ -103,7 +103,7 @@ enum Role { UNKNOWN } -type User implements Node { +type MasterUser implements Node { id: ID! username: String! age: Float! @@ -111,6 +111,17 @@ type User implements Node { role: Role! } +type MasterUserConnection { + totalCount: Int! + pageInfo: PageInfo! + edges: [MasterUserEdge] +} + +type MasterUserEdge { + node: MasterUser + cursor: Cursor! +} + type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! diff --git a/entgql/internal/todoplugin/todo.resolvers.go b/entgql/internal/todoplugin/todo.resolvers.go index 39837efa7..d0167ac9a 100644 --- a/entgql/internal/todoplugin/todo.resolvers.go +++ b/entgql/internal/todoplugin/todo.resolvers.go @@ -24,6 +24,14 @@ import ( "entgo.io/contrib/entgql/internal/todoplugin/ent" ) +func (r *masterUserResolver) Age(ctx context.Context, obj *ent.User) (float64, error) { + return float64(obj.Age), nil +} + +func (r *masterUserResolver) Amount(ctx context.Context, obj *ent.User) (float64, error) { + return float64(obj.Amount), nil +} + func (r *mutationResolver) CreateTodo(ctx context.Context, todo TodoInput) (*ent.Todo, error) { client := ent.FromContext(ctx) return client.Todo. @@ -61,13 +69,8 @@ func (r *todoResolver) Category(ctx context.Context, obj *ent.Todo) (*ent.Catego panic(fmt.Errorf("not implemented")) } -func (r *userResolver) Age(ctx context.Context, obj *ent.User) (float64, error) { - return float64(obj.Age), nil -} - -func (r *userResolver) Amount(ctx context.Context, obj *ent.User) (float64, error) { - return float64(obj.Amount), nil -} +// MasterUser returns MasterUserResolver implementation. +func (r *Resolver) MasterUser() MasterUserResolver { return &masterUserResolver{r} } // Mutation returns MutationResolver implementation. func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } @@ -78,10 +81,7 @@ func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } // Todo returns TodoResolver implementation. func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } -// User returns UserResolver implementation. -func (r *Resolver) User() UserResolver { return &userResolver{r} } - +type masterUserResolver struct{ *Resolver } type mutationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } type todoResolver struct{ *Resolver } -type userResolver struct{ *Resolver } diff --git a/entgql/template.go b/entgql/template.go index f9fc8e0e8..6a2d69643 100644 --- a/entgql/template.go +++ b/entgql/template.go @@ -17,6 +17,7 @@ package entgql import ( "embed" "errors" + "fmt" "os" "path/filepath" "strings" @@ -64,11 +65,12 @@ var ( // TemplateFuncs contains the extra template functions used by entgql. TemplateFuncs = template.FuncMap{ - "fieldCollections": fieldCollections, - "filterEdges": FilterEdges, - "filterFields": FilterFields, - "filterNodes": FilterNodes, - "findIDType": FindIDType, + "fieldCollections": fieldCollections, + "filterEdges": FilterEdges, + "filterFields": FilterFields, + "filterNodes": FilterNodes, + "findIDType": FindIDType, + "nodePaginationNames": NodePaginationNames, } //go:embed template/* @@ -81,6 +83,7 @@ func parseT(path string) *gen.Template { ParseFS(templates, path)) } +// FindIDType returns the type of the ID field of the given type. func FindIDType(nodes []*gen.Type, defaultType *field.TypeInfo) (*field.TypeInfo, error) { t := defaultType if len(nodes) > 0 { @@ -132,6 +135,7 @@ func fieldCollections(edges []*gen.Edge) (map[string]fieldCollection, error) { return result, nil } +// FilterNodes filters out nodes that should not be included in the GraphQL schema. func FilterNodes(nodes []*gen.Type) ([]*gen.Type, error) { var filteredNodes []*gen.Type for _, n := range nodes { @@ -149,6 +153,7 @@ func FilterNodes(nodes []*gen.Type) ([]*gen.Type, error) { return filteredNodes, nil } +// FilterEdges filters out edges that should not be included in the GraphQL schema. func FilterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { var filteredEdges []*gen.Edge for _, e := range edges { @@ -175,6 +180,7 @@ func FilterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { return filteredEdges, nil } +// FilterFields filters out fields that should not be included in the GraphQL schema. func FilterFields(fields []*gen.Field) ([]*gen.Field, error) { var filteredFields []*gen.Field for _, f := range fields { @@ -192,6 +198,33 @@ func FilterFields(fields []*gen.Field) ([]*gen.Field, error) { return filteredFields, nil } +// PaginationNames holds the names of the pagination fields. +type PaginationNames struct { + Node string + Edge string + Conn string +} + +// NodePaginationNames returns the names of the pagination types for the node. +func NodePaginationNames(t *gen.Type) (*PaginationNames, error) { + node := t.Name + ant, err := DecodeAnnotation(t.Annotations) + if err != nil { + return nil, err + } + if ant.Type != "" { + node = ant.Type + } + connName := fmt.Sprintf("%sConnection", node) + edgeName := fmt.Sprintf("%sEdge", node) + + return &PaginationNames{ + Conn: connName, + Edge: edgeName, + Node: node, + }, nil +} + // removeOldAssets removes files that were generated before v0.1.0. func removeOldAssets(next gen.Generator) gen.Generator { const prefix = "gql_" diff --git a/entgql/template/pagination.tmpl b/entgql/template/pagination.tmpl index 68ec056f6..5c26f8815 100644 --- a/entgql/template/pagination.tmpl +++ b/entgql/template/pagination.tmpl @@ -229,15 +229,22 @@ const ( {{- end }} {{- end }} -{{ $name := $node.Name -}} -{{ $edge := print $name "Edge" -}} +{{ $names := nodePaginationNames $node -}} +{{ $name := $names.Node -}} +{{ $conn := $names.Conn -}} +{{ $edge := $names.Edge -}} + +{{- if not (eq $name $node.Name) }} +// {{ $name }} is the type alias for {{ $node.Name }}. +type {{ $name }} = {{ $node.Name }} +{{- end}} + // {{ $edge }} is the edge representation of {{ $name }}. type {{ $edge }} struct { Node *{{ $name }} `json:"node"` Cursor Cursor `json:"cursor"` } -{{ $conn := print $name "Connection" -}} // {{ $conn }} is the connection containing edges to {{ $name }}. type {{ $conn }} struct { Edges []*{{ $edge }} `json:"edges"` From ce3256ad931edff23977cf3e55b5671cd7e9c2d3 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 11:08:03 +0000 Subject: [PATCH 10/23] feat: generate Edge, Connection types --- entgql/internal/todoplugin/cmd/entgqlgen.go | 4 +- entgql/plugin/plugin.go | 27 ++- entgql/plugin/plugin_config.go | 12 +- entgql/plugin/plugin_relay.go | 136 ++++++++++++++ entgql/plugin/plugin_relay_test.go | 195 ++++++++++++++++++++ entgql/plugin/plugin_test.go | 81 ++++++++ 6 files changed, 429 insertions(+), 26 deletions(-) create mode 100644 entgql/plugin/plugin_relay.go create mode 100644 entgql/plugin/plugin_relay_test.go diff --git a/entgql/internal/todoplugin/cmd/entgqlgen.go b/entgql/internal/todoplugin/cmd/entgqlgen.go index f80355a9e..c1856c6d2 100644 --- a/entgql/internal/todoplugin/cmd/entgqlgen.go +++ b/entgql/internal/todoplugin/cmd/entgqlgen.go @@ -48,7 +48,9 @@ func main() { os.Exit(2) } - entgqlPlugin, err := plugin.NewEntGQLPlugin(graph) + entgqlPlugin, err := plugin.NewEntGQLPlugin(graph, + plugin.WithRelaySpecification(true), + ) if err != nil { log.Fatalf("creating entgql plugin: %v", err) } diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index 888ec0617..5cfbc4cd8 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -103,7 +103,7 @@ func (e *EntGQL) InjectSourceEarly() *ast.Source { func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { types := map[string]*ast.Definition{} for _, node := range e.nodes { - ant, err := decodeAnnotation(node.Annotations) + ant, err := entgql.DecodeAnnotation(node.Annotations) if err != nil { return nil, err } @@ -132,6 +132,16 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { Fields: fields, Interfaces: interfaces, } + + // TODO(giautm): Added RelayConnection annotation check + if e.relaySpec { + defs, err := relayConnectionTypes(node) + if err != nil { + return nil, err + } + + insertDefinitions(types, defs...) + } } return types, nil @@ -162,7 +172,7 @@ func (e *EntGQL) buildTypeFields(t *gen.Type) (ast.FieldList, error) { } func (e *EntGQL) typeField(f *gen.Field, isID bool) ([]*ast.FieldDefinition, error) { - ant, err := decodeAnnotation(f.Annotations) + ant, err := entgql.DecodeAnnotation(f.Annotations) if err != nil { return nil, err } @@ -227,19 +237,6 @@ func (e *EntGQL) typeFromField(f *gen.Field, idField bool, userDefinedType strin } } -func decodeAnnotation(annotations gen.Annotations) (*entgql.Annotation, error) { - ant := &entgql.Annotation{} - if annotations == nil || annotations[ant.Name()] == nil { - return ant, nil - } - - err := ant.Decode(annotations[ant.Name()]) - if err != nil { - return nil, err - } - return ant, nil -} - func printSchema(schema *ast.Schema) string { sb := &strings.Builder{} formatter. diff --git a/entgql/plugin/plugin_config.go b/entgql/plugin/plugin_config.go index f5fa30c59..47c88bb09 100644 --- a/entgql/plugin/plugin_config.go +++ b/entgql/plugin/plugin_config.go @@ -17,18 +17,10 @@ package plugin import ( "fmt" + "entgo.io/contrib/entgql" "github.com/99designs/gqlgen/codegen/config" ) -var ( - // RelayCursor is the name of the cursor type - RelayCursor = "Cursor" - // RelayNode is the name of the interface that all nodes implement - RelayNode = "Node" - // RelayPageInfo is the name of the PageInfo type - RelayPageInfo = "PageInfo" -) - // MutateConfig implements the ConfigMutator interface func (e *EntGQL) MutateConfig(cfg *config.Config) error { if e.relaySpec { @@ -45,7 +37,7 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { } for _, node := range e.nodes { - ant, err := decodeAnnotation(node.Annotations) + ant, err := entgql.DecodeAnnotation(node.Annotations) if err != nil { return err } diff --git a/entgql/plugin/plugin_relay.go b/entgql/plugin/plugin_relay.go new file mode 100644 index 000000000..2fdc9c549 --- /dev/null +++ b/entgql/plugin/plugin_relay.go @@ -0,0 +1,136 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "entgo.io/contrib/entgql" + "entgo.io/ent/entc/gen" + "github.com/vektah/gqlparser/v2/ast" +) + +var ( + // RelayCursor is the name of the cursor type + RelayCursor = "Cursor" + // RelayNode is the name of the interface that all nodes implement + RelayNode = "Node" + // RelayPageInfo is the name of the PageInfo type + RelayPageInfo = "PageInfo" +) + +func relayBuiltinTypes() []*ast.Definition { + return []*ast.Definition{ + { + Name: RelayCursor, + Kind: ast.Scalar, + Description: `Define a Relay Cursor type: +https://relay.dev/graphql/connections.htm#sec-Cursor`, + }, + { + Name: RelayNode, + Kind: ast.Interface, + Description: `An object with an ID. +Follows the [Relay Global Object Identification Specification](https://relay.dev/graphql/objectidentification.htm)`, + Fields: []*ast.FieldDefinition{ + { + Name: "id", + Type: ast.NonNullNamedType("ID", nil), + Description: "The id of the object.", + }, + }, + }, + { + Name: RelayPageInfo, + Kind: ast.Object, + Description: `Information about pagination in a connection. +https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo`, + Fields: []*ast.FieldDefinition{ + { + Name: "hasNextPage", + Type: ast.NonNullNamedType("Boolean", nil), + Description: "When paginating forwards, are there more items?", + }, + { + Name: "hasPreviousPage", + Type: ast.NonNullNamedType("Boolean", nil), + Description: "When paginating backwards, are there more items?", + }, + { + Name: "startCursor", + Type: ast.NamedType("Cursor", nil), + Description: "When paginating backwards, the cursor to continue.", + }, + { + Name: "endCursor", + Type: ast.NamedType("Cursor", nil), + Description: "When paginating forwards, the cursor to continue.", + }, + }, + }, + } +} + +func relayConnectionTypes(t *gen.Type) ([]*ast.Definition, error) { + pagination, err := entgql.NodePaginationNames(t) + if err != nil { + return nil, err + } + + return []*ast.Definition{ + { + Name: pagination.Edge, + Kind: ast.Object, + Description: "An edge in a connection.", + Fields: []*ast.FieldDefinition{ + { + Name: "node", + Type: ast.NamedType(pagination.Node, nil), + Description: "The item at the end of the edge.", + }, + { + Name: "cursor", + Type: ast.NonNullNamedType("Cursor", nil), + Description: "A cursor for use in pagination.", + }, + }, + }, + { + Name: pagination.Conn, + Kind: ast.Object, + Description: "A connection to a list of items.", + Fields: []*ast.FieldDefinition{ + { + Name: "edges", + Type: ast.ListType(ast.NamedType(pagination.Edge, nil), nil), + Description: "A list of edges.", + }, + { + Name: "pageInfo", + Type: ast.NonNullNamedType("PageInfo", nil), + Description: "Information to aid in pagination.", + }, + { + Name: "totalCount", + Type: ast.NonNullNamedType("Int", nil), + }, + }, + }, + }, nil +} + +func insertDefinitions(types map[string]*ast.Definition, defs ...*ast.Definition) { + for _, d := range defs { + types[d.Name] = d + } +} diff --git a/entgql/plugin/plugin_relay_test.go b/entgql/plugin/plugin_relay_test.go new file mode 100644 index 000000000..26bde868a --- /dev/null +++ b/entgql/plugin/plugin_relay_test.go @@ -0,0 +1,195 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package plugin + +import ( + "reflect" + "testing" + + "entgo.io/ent/entc/gen" + "github.com/vektah/gqlparser/v2/ast" +) + +func Test_relayConnectionTypes(t *testing.T) { + type args struct { + t *gen.Type + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "Todo", + args: args{ + t: &gen.Type{ + Name: "Todo", + }, + }, + want: `""" +A connection to a list of items. +""" +type TodoConnection { + """ + A list of edges. + """ + edges: [TodoEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type TodoEdge { + """ + The item at the end of the edge. + """ + node: Todo + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} +`, + }, + { + name: "Todo_with_type", + args: args{ + t: &gen.Type{ + Name: "Todo", + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "Type": "SuperTodo", + }, + }, + }, + }, + want: `""" +A connection to a list of items. +""" +type SuperTodoConnection { + """ + A list of edges. + """ + edges: [SuperTodoEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type SuperTodoEdge { + """ + The item at the end of the edge. + """ + node: SuperTodo + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} +`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := relayConnectionTypes(tt.args.t) + if (err != nil) != tt.wantErr { + t.Errorf("relayConnection() error = %v, wantErr %v", err, tt.wantErr) + return + } + + s := &ast.Schema{ + Types: map[string]*ast.Definition{}, + } + insertDefinitions(s.Types, got...) + gots := printSchema(s) + if !reflect.DeepEqual(gots, tt.want) { + t.Errorf("relayConnection() = %v, want %v", gots, tt.want) + } + }) + } +} + +func Test_relayBuiltinTypes(t *testing.T) { + tests := []struct { + name string + want string + }{ + { + name: "relayBuiltinTypes", + want: `""" +Define a Relay Cursor type: +https://relay.dev/graphql/connections.htm#sec-Cursor +""" +scalar Cursor +""" +An object with an ID. +Follows the [Relay Global Object Identification Specification](https://relay.dev/graphql/objectidentification.htm) +""" +interface Node { + """ + The id of the object. + """ + id: ID! +} +""" +Information about pagination in a connection. +https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo +""" +type PageInfo { + """ + When paginating forwards, are there more items? + """ + hasNextPage: Boolean! + """ + When paginating backwards, are there more items? + """ + hasPreviousPage: Boolean! + """ + When paginating backwards, the cursor to continue. + """ + startCursor: Cursor + """ + When paginating forwards, the cursor to continue. + """ + endCursor: Cursor +} +`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := relayBuiltinTypes() + + s := &ast.Schema{ + Types: map[string]*ast.Definition{}, + } + insertDefinitions(s.Types, got...) + gots := printSchema(s) + if !reflect.DeepEqual(gots, tt.want) { + t.Errorf("relayBuiltinTypes() = %v, want %v", gots, tt.want) + } + }) + } +} diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go index f0b2938fc..3c3cd4985 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/plugin/plugin_test.go @@ -79,6 +79,33 @@ func TestEntGQL_buildTypes_relay(t *testing.T) { duration: Duration! count: Uint64! } +""" +A connection to a list of items. +""" +type CategoryConnection { + """ + A list of edges. + """ + edges: [CategoryEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type CategoryEdge { + """ + The item at the end of the edge. + """ + node: Category + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} type MasterUser implements Node { id: ID! username: String! @@ -86,6 +113,33 @@ type MasterUser implements Node { amount: Float! role: Role! } +""" +A connection to a list of items. +""" +type MasterUserConnection { + """ + A list of edges. + """ + edges: [MasterUserEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type MasterUserEdge { + """ + The item at the end of the edge. + """ + node: MasterUser + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} type Todo implements Node { id: ID! createdAt: Time! @@ -94,6 +148,33 @@ type Todo implements Node { priority: Int! text: String! } +""" +A connection to a list of items. +""" +type TodoConnection { + """ + A list of edges. + """ + edges: [TodoEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type TodoEdge { + """ + The item at the end of the edge. + """ + node: Todo + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} `, printSchema(&ast.Schema{ Types: types, })) From 28e280becc684417c3ca878933f5f3a52119b272 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 18:34:23 +0000 Subject: [PATCH 11/23] feat: mapping config for fields of the entity --- entgql/internal/todoplugin/ent/gql_node.go | 10 +- .../internal/todoplugin/ent/migrate/schema.go | 1 + entgql/internal/todoplugin/ent/mutation.go | 106 ++++++++++++-- entgql/internal/todoplugin/ent/schema/user.go | 3 + entgql/internal/todoplugin/ent/user.go | 15 +- entgql/internal/todoplugin/ent/user/user.go | 3 + entgql/internal/todoplugin/ent/user/where.go | 132 ++++++++++++++++++ entgql/internal/todoplugin/ent/user_create.go | 22 +++ entgql/internal/todoplugin/ent/user_update.go | 66 +++++++++ entgql/plugin/plugin_config.go | 47 +++++++ entgql/plugin/plugin_config_test.go | 74 +++++++++- entgql/plugin/plugin_test.go | 4 +- 12 files changed, 459 insertions(+), 24 deletions(-) diff --git a/entgql/internal/todoplugin/ent/gql_node.go b/entgql/internal/todoplugin/ent/gql_node.go index 3fd7d50f4..ac419ec85 100644 --- a/entgql/internal/todoplugin/ent/gql_node.go +++ b/entgql/internal/todoplugin/ent/gql_node.go @@ -206,7 +206,7 @@ func (u *User) Node(ctx context.Context) (node *Node, err error) { node = &Node{ ID: u.ID, Type: "User", - Fields: make([]*Field, 4), + Fields: make([]*Field, 5), Edges: make([]*Edge, 0), } var buf []byte @@ -242,6 +242,14 @@ func (u *User) Node(ctx context.Context) (node *Node, err error) { Name: "role", Value: string(buf), } + if buf, err = json.Marshal(u.NullableString); err != nil { + return nil, err + } + node.Fields[4] = &Field{ + Type: "string", + Name: "nullable_string", + Value: string(buf), + } return node, nil } diff --git a/entgql/internal/todoplugin/ent/migrate/schema.go b/entgql/internal/todoplugin/ent/migrate/schema.go index 62e4389a9..029bec35f 100644 --- a/entgql/internal/todoplugin/ent/migrate/schema.go +++ b/entgql/internal/todoplugin/ent/migrate/schema.go @@ -76,6 +76,7 @@ var ( {Name: "age", Type: field.TypeInt}, {Name: "amount", Type: field.TypeFloat64}, {Name: "role", Type: field.TypeEnum, Enums: []string{"ADMIN", "USER", "UNKNOWN"}}, + {Name: "nullable_string", Type: field.TypeString, Nullable: true}, } // UsersTable holds the schema information for the "users" table. UsersTable = &schema.Table{ diff --git a/entgql/internal/todoplugin/ent/mutation.go b/entgql/internal/todoplugin/ent/mutation.go index 1c26346ea..1bef8836c 100644 --- a/entgql/internal/todoplugin/ent/mutation.go +++ b/entgql/internal/todoplugin/ent/mutation.go @@ -1591,19 +1591,20 @@ func (m *TodoMutation) ResetEdge(name string) error { // UserMutation represents an operation that mutates the User nodes in the graph. type UserMutation struct { config - op Op - typ string - id *int - username *string - age *int - addage *int - amount *schema.Amount - addamount *schema.Amount - role *role.Role - clearedFields map[string]struct{} - done bool - oldValue func(context.Context) (*User, error) - predicates []predicate.User + op Op + typ string + id *int + username *string + age *int + addage *int + amount *schema.Amount + addamount *schema.Amount + role *role.Role + nullable_string *string + clearedFields map[string]struct{} + done bool + oldValue func(context.Context) (*User, error) + predicates []predicate.User } var _ ent.Mutation = (*UserMutation)(nil) @@ -1894,6 +1895,55 @@ func (m *UserMutation) ResetRole() { m.role = nil } +// SetNullableString sets the "nullable_string" field. +func (m *UserMutation) SetNullableString(s string) { + m.nullable_string = &s +} + +// NullableString returns the value of the "nullable_string" field in the mutation. +func (m *UserMutation) NullableString() (r string, exists bool) { + v := m.nullable_string + if v == nil { + return + } + return *v, true +} + +// OldNullableString returns the old "nullable_string" field's value of the User entity. +// If the User object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *UserMutation) OldNullableString(ctx context.Context) (v *string, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldNullableString is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldNullableString requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldNullableString: %w", err) + } + return oldValue.NullableString, nil +} + +// ClearNullableString clears the value of the "nullable_string" field. +func (m *UserMutation) ClearNullableString() { + m.nullable_string = nil + m.clearedFields[user.FieldNullableString] = struct{}{} +} + +// NullableStringCleared returns if the "nullable_string" field was cleared in this mutation. +func (m *UserMutation) NullableStringCleared() bool { + _, ok := m.clearedFields[user.FieldNullableString] + return ok +} + +// ResetNullableString resets all changes to the "nullable_string" field. +func (m *UserMutation) ResetNullableString() { + m.nullable_string = nil + delete(m.clearedFields, user.FieldNullableString) +} + // Where appends a list predicates to the UserMutation builder. func (m *UserMutation) Where(ps ...predicate.User) { m.predicates = append(m.predicates, ps...) @@ -1913,7 +1963,7 @@ func (m *UserMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *UserMutation) Fields() []string { - fields := make([]string, 0, 4) + fields := make([]string, 0, 5) if m.username != nil { fields = append(fields, user.FieldUsername) } @@ -1926,6 +1976,9 @@ func (m *UserMutation) Fields() []string { if m.role != nil { fields = append(fields, user.FieldRole) } + if m.nullable_string != nil { + fields = append(fields, user.FieldNullableString) + } return fields } @@ -1942,6 +1995,8 @@ func (m *UserMutation) Field(name string) (ent.Value, bool) { return m.Amount() case user.FieldRole: return m.Role() + case user.FieldNullableString: + return m.NullableString() } return nil, false } @@ -1959,6 +2014,8 @@ func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, er return m.OldAmount(ctx) case user.FieldRole: return m.OldRole(ctx) + case user.FieldNullableString: + return m.OldNullableString(ctx) } return nil, fmt.Errorf("unknown User field %s", name) } @@ -1996,6 +2053,13 @@ func (m *UserMutation) SetField(name string, value ent.Value) error { } m.SetRole(v) return nil + case user.FieldNullableString: + v, ok := value.(string) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetNullableString(v) + return nil } return fmt.Errorf("unknown User field %s", name) } @@ -2052,7 +2116,11 @@ func (m *UserMutation) AddField(name string, value ent.Value) error { // ClearedFields returns all nullable fields that were cleared during this // mutation. func (m *UserMutation) ClearedFields() []string { - return nil + var fields []string + if m.FieldCleared(user.FieldNullableString) { + fields = append(fields, user.FieldNullableString) + } + return fields } // FieldCleared returns a boolean indicating if a field with the given name was @@ -2065,6 +2133,11 @@ func (m *UserMutation) FieldCleared(name string) bool { // ClearField clears the value of the field with the given name. It returns an // error if the field is not defined in the schema. func (m *UserMutation) ClearField(name string) error { + switch name { + case user.FieldNullableString: + m.ClearNullableString() + return nil + } return fmt.Errorf("unknown User nullable field %s", name) } @@ -2084,6 +2157,9 @@ func (m *UserMutation) ResetField(name string) error { case user.FieldRole: m.ResetRole() return nil + case user.FieldNullableString: + m.ResetNullableString() + return nil } return fmt.Errorf("unknown User field %s", name) } diff --git a/entgql/internal/todoplugin/ent/schema/user.go b/entgql/internal/todoplugin/ent/schema/user.go index e9fe108e6..3343f30bb 100644 --- a/entgql/internal/todoplugin/ent/schema/user.go +++ b/entgql/internal/todoplugin/ent/schema/user.go @@ -48,6 +48,9 @@ func (User) Fields() []ent.Field { }), field.Enum("role"). GoType(role.Unknown), + field.String("nullable_string"). + Nillable(). + Optional(), } } diff --git a/entgql/internal/todoplugin/ent/user.go b/entgql/internal/todoplugin/ent/user.go index 78365993e..a43633489 100644 --- a/entgql/internal/todoplugin/ent/user.go +++ b/entgql/internal/todoplugin/ent/user.go @@ -39,6 +39,8 @@ type User struct { Amount schema.Amount `json:"amount,omitempty"` // Role holds the value of the "role" field. Role role.Role `json:"role,omitempty"` + // NullableString holds the value of the "nullable_string" field. + NullableString *string `json:"nullable_string,omitempty"` } // scanValues returns the types for scanning values from sql.Rows. @@ -50,7 +52,7 @@ func (*User) scanValues(columns []string) ([]interface{}, error) { values[i] = new(sql.NullFloat64) case user.FieldID, user.FieldAge: values[i] = new(sql.NullInt64) - case user.FieldUsername, user.FieldRole: + case user.FieldUsername, user.FieldRole, user.FieldNullableString: values[i] = new(sql.NullString) default: return nil, fmt.Errorf("unexpected column %q for type User", columns[i]) @@ -97,6 +99,13 @@ func (u *User) assignValues(columns []string, values []interface{}) error { } else if value.Valid { u.Role = role.Role(value.String) } + case user.FieldNullableString: + if value, ok := values[i].(*sql.NullString); !ok { + return fmt.Errorf("unexpected type %T for field nullable_string", values[i]) + } else if value.Valid { + u.NullableString = new(string) + *u.NullableString = value.String + } } } return nil @@ -133,6 +142,10 @@ func (u *User) String() string { builder.WriteString(fmt.Sprintf("%v", u.Amount)) builder.WriteString(", role=") builder.WriteString(fmt.Sprintf("%v", u.Role)) + if v := u.NullableString; v != nil { + builder.WriteString(", nullable_string=") + builder.WriteString(*v) + } builder.WriteByte(')') return builder.String() } diff --git a/entgql/internal/todoplugin/ent/user/user.go b/entgql/internal/todoplugin/ent/user/user.go index fdc45b587..42c0d63ab 100644 --- a/entgql/internal/todoplugin/ent/user/user.go +++ b/entgql/internal/todoplugin/ent/user/user.go @@ -36,6 +36,8 @@ const ( FieldAmount = "amount" // FieldRole holds the string denoting the role field in the database. FieldRole = "role" + // FieldNullableString holds the string denoting the nullable_string field in the database. + FieldNullableString = "nullable_string" // Table holds the table name of the user in the database. Table = "users" ) @@ -47,6 +49,7 @@ var Columns = []string{ FieldAge, FieldAmount, FieldRole, + FieldNullableString, } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/entgql/internal/todoplugin/ent/user/where.go b/entgql/internal/todoplugin/ent/user/where.go index 115b1956c..432b2400c 100644 --- a/entgql/internal/todoplugin/ent/user/where.go +++ b/entgql/internal/todoplugin/ent/user/where.go @@ -142,6 +142,13 @@ func Amount(v schema.Amount) predicate.User { }) } +// NullableString applies equality check predicate on the "nullable_string" field. It's identical to NullableStringEQ. +func NullableString(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldNullableString), v)) + }) +} + // UsernameEQ applies the EQ predicate on the "username" field. func UsernameEQ(v string) predicate.User { return predicate.User(func(s *sql.Selector) { @@ -461,6 +468,131 @@ func RoleNotIn(vs ...role.Role) predicate.User { }) } +// NullableStringEQ applies the EQ predicate on the "nullable_string" field. +func NullableStringEQ(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EQ(s.C(FieldNullableString), v)) + }) +} + +// NullableStringNEQ applies the NEQ predicate on the "nullable_string" field. +func NullableStringNEQ(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NEQ(s.C(FieldNullableString), v)) + }) +} + +// NullableStringIn applies the In predicate on the "nullable_string" field. +func NullableStringIn(vs ...string) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.In(s.C(FieldNullableString), v...)) + }) +} + +// NullableStringNotIn applies the NotIn predicate on the "nullable_string" field. +func NullableStringNotIn(vs ...string) predicate.User { + v := make([]interface{}, len(vs)) + for i := range v { + v[i] = vs[i] + } + return predicate.User(func(s *sql.Selector) { + // if not arguments were provided, append the FALSE constants, + // since we can't apply "IN ()". This will make this predicate falsy. + if len(v) == 0 { + s.Where(sql.False()) + return + } + s.Where(sql.NotIn(s.C(FieldNullableString), v...)) + }) +} + +// NullableStringGT applies the GT predicate on the "nullable_string" field. +func NullableStringGT(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GT(s.C(FieldNullableString), v)) + }) +} + +// NullableStringGTE applies the GTE predicate on the "nullable_string" field. +func NullableStringGTE(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.GTE(s.C(FieldNullableString), v)) + }) +} + +// NullableStringLT applies the LT predicate on the "nullable_string" field. +func NullableStringLT(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LT(s.C(FieldNullableString), v)) + }) +} + +// NullableStringLTE applies the LTE predicate on the "nullable_string" field. +func NullableStringLTE(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.LTE(s.C(FieldNullableString), v)) + }) +} + +// NullableStringContains applies the Contains predicate on the "nullable_string" field. +func NullableStringContains(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.Contains(s.C(FieldNullableString), v)) + }) +} + +// NullableStringHasPrefix applies the HasPrefix predicate on the "nullable_string" field. +func NullableStringHasPrefix(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.HasPrefix(s.C(FieldNullableString), v)) + }) +} + +// NullableStringHasSuffix applies the HasSuffix predicate on the "nullable_string" field. +func NullableStringHasSuffix(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.HasSuffix(s.C(FieldNullableString), v)) + }) +} + +// NullableStringIsNil applies the IsNil predicate on the "nullable_string" field. +func NullableStringIsNil() predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.IsNull(s.C(FieldNullableString))) + }) +} + +// NullableStringNotNil applies the NotNil predicate on the "nullable_string" field. +func NullableStringNotNil() predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.NotNull(s.C(FieldNullableString))) + }) +} + +// NullableStringEqualFold applies the EqualFold predicate on the "nullable_string" field. +func NullableStringEqualFold(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.EqualFold(s.C(FieldNullableString), v)) + }) +} + +// NullableStringContainsFold applies the ContainsFold predicate on the "nullable_string" field. +func NullableStringContainsFold(v string) predicate.User { + return predicate.User(func(s *sql.Selector) { + s.Where(sql.ContainsFold(s.C(FieldNullableString), v)) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.User) predicate.User { return predicate.User(func(s *sql.Selector) { diff --git a/entgql/internal/todoplugin/ent/user_create.go b/entgql/internal/todoplugin/ent/user_create.go index feab95b10..4daaca936 100644 --- a/entgql/internal/todoplugin/ent/user_create.go +++ b/entgql/internal/todoplugin/ent/user_create.go @@ -59,6 +59,20 @@ func (uc *UserCreate) SetRole(r role.Role) *UserCreate { return uc } +// SetNullableString sets the "nullable_string" field. +func (uc *UserCreate) SetNullableString(s string) *UserCreate { + uc.mutation.SetNullableString(s) + return uc +} + +// SetNillableNullableString sets the "nullable_string" field if the given value is not nil. +func (uc *UserCreate) SetNillableNullableString(s *string) *UserCreate { + if s != nil { + uc.SetNullableString(*s) + } + return uc +} + // SetID sets the "id" field. func (uc *UserCreate) SetID(i int) *UserCreate { uc.mutation.SetID(i) @@ -225,6 +239,14 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) { }) _node.Role = value } + if value, ok := uc.mutation.NullableString(); ok { + _spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldNullableString, + }) + _node.NullableString = &value + } return _node, _spec } diff --git a/entgql/internal/todoplugin/ent/user_update.go b/entgql/internal/todoplugin/ent/user_update.go index c1aecd272..edf8a2204 100644 --- a/entgql/internal/todoplugin/ent/user_update.go +++ b/entgql/internal/todoplugin/ent/user_update.go @@ -81,6 +81,26 @@ func (uu *UserUpdate) SetRole(r role.Role) *UserUpdate { return uu } +// SetNullableString sets the "nullable_string" field. +func (uu *UserUpdate) SetNullableString(s string) *UserUpdate { + uu.mutation.SetNullableString(s) + return uu +} + +// SetNillableNullableString sets the "nullable_string" field if the given value is not nil. +func (uu *UserUpdate) SetNillableNullableString(s *string) *UserUpdate { + if s != nil { + uu.SetNullableString(*s) + } + return uu +} + +// ClearNullableString clears the value of the "nullable_string" field. +func (uu *UserUpdate) ClearNullableString() *UserUpdate { + uu.mutation.ClearNullableString() + return uu +} + // Mutation returns the UserMutation object of the builder. func (uu *UserUpdate) Mutation() *UserMutation { return uu.mutation @@ -216,6 +236,19 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: user.FieldRole, }) } + if value, ok := uu.mutation.NullableString(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldNullableString, + }) + } + if uu.mutation.NullableStringCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldNullableString, + }) + } if n, err = sqlgraph.UpdateNodes(ctx, uu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { err = &NotFoundError{user.Label} @@ -273,6 +306,26 @@ func (uuo *UserUpdateOne) SetRole(r role.Role) *UserUpdateOne { return uuo } +// SetNullableString sets the "nullable_string" field. +func (uuo *UserUpdateOne) SetNullableString(s string) *UserUpdateOne { + uuo.mutation.SetNullableString(s) + return uuo +} + +// SetNillableNullableString sets the "nullable_string" field if the given value is not nil. +func (uuo *UserUpdateOne) SetNillableNullableString(s *string) *UserUpdateOne { + if s != nil { + uuo.SetNullableString(*s) + } + return uuo +} + +// ClearNullableString clears the value of the "nullable_string" field. +func (uuo *UserUpdateOne) ClearNullableString() *UserUpdateOne { + uuo.mutation.ClearNullableString() + return uuo +} + // Mutation returns the UserMutation object of the builder. func (uuo *UserUpdateOne) Mutation() *UserMutation { return uuo.mutation @@ -432,6 +485,19 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error) Column: user.FieldRole, }) } + if value, ok := uuo.mutation.NullableString(); ok { + _spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Value: value, + Column: user.FieldNullableString, + }) + } + if uuo.mutation.NullableStringCleared() { + _spec.Fields.Clear = append(_spec.Fields.Clear, &sqlgraph.FieldSpec{ + Type: field.TypeString, + Column: user.FieldNullableString, + }) + } _node = &User{config: uuo.config} _spec.Assign = _node.assignValues _spec.ScanValues = _node.scanValues diff --git a/entgql/plugin/plugin_config.go b/entgql/plugin/plugin_config.go index 47c88bb09..13a582acf 100644 --- a/entgql/plugin/plugin_config.go +++ b/entgql/plugin/plugin_config.go @@ -52,6 +52,53 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { if !cfg.Models.Exists(name) { cfg.Models.Add(name, e.entGoType(node.Name)) } + + for _, field := range node.Fields { + ant, err := entgql.DecodeAnnotation(field.Annotations) + if err != nil { + return err + } + if ant.Skip { + continue + } + + goType := "" + switch { + case field.IsEnum(): + goType = fmt.Sprintf("%s/%s", e.graph.Package, field.Type.Ident) + case field.IsOther(): + goType = fmt.Sprintf("%s.%s", field.Type.RType.PkgPath, field.Type.RType.Name) + default: + continue + } + + // NOTE(giautm): I'm not sure this is + // the right approach, but it passed the test + defs, err := e.typeFromField(field, false, ant.Type) + if err != nil { + return err + } + name := defs.Name() + + if !cfg.Models.Exists(name) { + cfg.Models.Add(name, goType) + } + } + + // TODO(giautm): Added RelayConnection annotation check + if e.relaySpec { + pagination, err := entgql.NodePaginationNames(node) + if err != nil { + return err + } + + if !cfg.Models.Exists(pagination.Conn) { + cfg.Models.Add(pagination.Conn, e.entGoType(pagination.Conn)) + } + if !cfg.Models.Exists(pagination.Edge) { + cfg.Models.Add(pagination.Edge, e.entGoType(pagination.Edge)) + } + } } return nil diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go index 61972610e..f704dbeed 100644 --- a/entgql/plugin/plugin_config_test.go +++ b/entgql/plugin/plugin_config_test.go @@ -17,6 +17,7 @@ package plugin import ( "testing" + "entgo.io/ent/entc" "entgo.io/ent/entc/gen" "entgo.io/ent/schema/field" "github.com/99designs/gqlgen/codegen/config" @@ -128,12 +129,73 @@ func TestModifyConfig_relay(t *testing.T) { require.NoError(t, err) expected := config.DefaultConfig() expected.Models = map[string]config.TypeMapEntry{ - "Cursor": {Model: []string{"example.com.Cursor"}}, - "Group": {Model: []string{"example.com.Group"}}, - "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, - "Node": {Model: []string{"example.com.Noder"}}, - "PageInfo": {Model: []string{"example.com.PageInfo"}}, - "Todo": {Model: []string{"example.com.Todo"}}, + "Cursor": {Model: []string{"example.com.Cursor"}}, + "Group": {Model: []string{"example.com.Group"}}, + "GroupConnection": {Model: []string{"example.com.GroupConnection"}}, + "GroupEdge": {Model: []string{"example.com.GroupEdge"}}, + "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, + "GroupWithSortConnection": {Model: []string{"example.com.GroupWithSortConnection"}}, + "GroupWithSortEdge": {Model: []string{"example.com.GroupWithSortEdge"}}, + "Node": {Model: []string{"example.com.Noder"}}, + "PageInfo": {Model: []string{"example.com.PageInfo"}}, + "Todo": {Model: []string{"example.com.Todo"}}, + "TodoConnection": {Model: []string{"example.com.TodoConnection"}}, + "TodoEdge": {Model: []string{"example.com.TodoEdge"}}, + } + require.Equal(t, expected, cfg) +} + +func TestModifyConfig_todoplugin(t *testing.T) { + graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) + require.NoError(t, err) + + e, err := NewEntGQLPlugin(graph) + require.NoError(t, err) + cfg := config.DefaultConfig() + err = e.MutateConfig(cfg) + require.NoError(t, err) + expected := config.DefaultConfig() + expected.Models = map[string]config.TypeMapEntry{ + "Category": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Category"}}, + "CategoryStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status"}}, + "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig"}}, + "MasterUser": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.User"}}, + "Role": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role"}}, + "Status": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status"}}, + "Todo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Todo"}}, + "VisibilityStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus"}}, + } + require.Equal(t, expected, cfg) +} + +func TestModifyConfig_todoplugin_relay(t *testing.T) { + graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) + require.NoError(t, err) + + e, err := NewEntGQLPlugin(graph, WithRelaySpecification(true)) + require.NoError(t, err) + cfg := config.DefaultConfig() + err = e.MutateConfig(cfg) + require.NoError(t, err) + expected := config.DefaultConfig() + expected.Models = map[string]config.TypeMapEntry{ + "Category": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Category"}}, + "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig"}}, + "CategoryConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryConnection"}}, + "CategoryEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryEdge"}}, + "CategoryStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status"}}, + "Cursor": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Cursor"}}, + "MasterUser": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.User"}}, + "MasterUserConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserConnection"}}, + "MasterUserEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserEdge"}}, + "Node": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Noder"}}, + "PageInfo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.PageInfo"}}, + "Role": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role"}}, + "Status": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status"}}, + "Todo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Todo"}}, + "TodoConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoConnection"}}, + "TodoEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoEdge"}}, + "VisibilityStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus"}}, } require.Equal(t, expected, cfg) } diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go index 3c3cd4985..9a0c801cd 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/plugin/plugin_test.go @@ -47,6 +47,7 @@ type MasterUser { age: Float! amount: Float! role: Role! + nullableString: String } type Todo { id: ID! @@ -61,7 +62,7 @@ type Todo { })) } -func TestEntGQL_buildTypes_relay(t *testing.T) { +func TestEntGQL_buildTypes_todoplugin_relay(t *testing.T) { graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) require.NoError(t, err) plugin, err := NewEntGQLPlugin(graph, WithRelaySpecification(true)) @@ -112,6 +113,7 @@ type MasterUser implements Node { age: Float! amount: Float! role: Role! + nullableString: String } """ A connection to a list of items. From 9e8765273be79e779a1e9fe7578fcd031e2102a3 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 19:16:19 +0000 Subject: [PATCH 12/23] fix(plugin): mapping for Order/OrderField object --- entgql/plugin/plugin_config.go | 22 ++++++++++++++++++++-- entgql/plugin/plugin_config_test.go | 8 ++++++++ entgql/plugin/plugin_relay.go | 2 +- entgql/template.go | 18 ++++++++++-------- entgql/template/pagination.tmpl | 8 ++++---- 5 files changed, 43 insertions(+), 15 deletions(-) diff --git a/entgql/plugin/plugin_config.go b/entgql/plugin/plugin_config.go index 13a582acf..5e060afdc 100644 --- a/entgql/plugin/plugin_config.go +++ b/entgql/plugin/plugin_config.go @@ -53,6 +53,7 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { cfg.Models.Add(name, e.entGoType(node.Name)) } + hasOrderBy := false for _, field := range node.Fields { ant, err := entgql.DecodeAnnotation(field.Annotations) if err != nil { @@ -62,6 +63,11 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { continue } + // Check if this node has an OrderBy object + if ant.OrderField != "" { + hasOrderBy = true + } + goType := "" switch { case field.IsEnum(): @@ -92,12 +98,24 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { return err } - if !cfg.Models.Exists(pagination.Conn) { - cfg.Models.Add(pagination.Conn, e.entGoType(pagination.Conn)) + if !cfg.Models.Exists(pagination.Connection) { + cfg.Models.Add(pagination.Connection, e.entGoType(pagination.Connection)) } if !cfg.Models.Exists(pagination.Edge) { cfg.Models.Add(pagination.Edge, e.entGoType(pagination.Edge)) } + + if hasOrderBy { + if !cfg.Models.Exists("OrderDirection") { + cfg.Models.Add("OrderDirection", e.entGoType("OrderDirection")) + } + cfg.Models[pagination.Order] = config.TypeMapEntry{ + Model: []string{e.entGoType(pagination.Order)}, + } + cfg.Models[pagination.OrderField] = config.TypeMapEntry{ + Model: []string{e.entGoType(pagination.OrderField)}, + } + } } } diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go index f704dbeed..106c83df1 100644 --- a/entgql/plugin/plugin_config_test.go +++ b/entgql/plugin/plugin_config_test.go @@ -136,7 +136,10 @@ func TestModifyConfig_relay(t *testing.T) { "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, "GroupWithSortConnection": {Model: []string{"example.com.GroupWithSortConnection"}}, "GroupWithSortEdge": {Model: []string{"example.com.GroupWithSortEdge"}}, + "GroupWithSortOrder": {Model: []string{"example.com.GroupWithSortOrder"}}, + "GroupWithSortOrderField": {Model: []string{"example.com.GroupWithSortOrderField"}}, "Node": {Model: []string{"example.com.Noder"}}, + "OrderDirection": {Model: []string{"example.com.OrderDirection"}}, "PageInfo": {Model: []string{"example.com.PageInfo"}}, "Todo": {Model: []string{"example.com.Todo"}}, "TodoConnection": {Model: []string{"example.com.TodoConnection"}}, @@ -183,18 +186,23 @@ func TestModifyConfig_todoplugin_relay(t *testing.T) { "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig"}}, "CategoryConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryConnection"}}, "CategoryEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryEdge"}}, + "CategoryOrder": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrder"}}, + "CategoryOrderField": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrderField"}}, "CategoryStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status"}}, "Cursor": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Cursor"}}, "MasterUser": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.User"}}, "MasterUserConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserConnection"}}, "MasterUserEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserEdge"}}, "Node": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Noder"}}, + "OrderDirection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.OrderDirection"}}, "PageInfo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.PageInfo"}}, "Role": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role"}}, "Status": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status"}}, "Todo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Todo"}}, "TodoConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoConnection"}}, "TodoEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoEdge"}}, + "TodoOrder": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoOrder"}}, + "TodoOrderField": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoOrderField"}}, "VisibilityStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus"}}, } require.Equal(t, expected, cfg) diff --git a/entgql/plugin/plugin_relay.go b/entgql/plugin/plugin_relay.go index 2fdc9c549..fb160a9ad 100644 --- a/entgql/plugin/plugin_relay.go +++ b/entgql/plugin/plugin_relay.go @@ -106,7 +106,7 @@ func relayConnectionTypes(t *gen.Type) ([]*ast.Definition, error) { }, }, { - Name: pagination.Conn, + Name: pagination.Connection, Kind: ast.Object, Description: "A connection to a list of items.", Fields: []*ast.FieldDefinition{ diff --git a/entgql/template.go b/entgql/template.go index 6a2d69643..4e7a6fc31 100644 --- a/entgql/template.go +++ b/entgql/template.go @@ -200,9 +200,11 @@ func FilterFields(fields []*gen.Field) ([]*gen.Field, error) { // PaginationNames holds the names of the pagination fields. type PaginationNames struct { - Node string - Edge string - Conn string + Connection string + Edge string + Node string + Order string + OrderField string } // NodePaginationNames returns the names of the pagination types for the node. @@ -215,13 +217,13 @@ func NodePaginationNames(t *gen.Type) (*PaginationNames, error) { if ant.Type != "" { node = ant.Type } - connName := fmt.Sprintf("%sConnection", node) - edgeName := fmt.Sprintf("%sEdge", node) return &PaginationNames{ - Conn: connName, - Edge: edgeName, - Node: node, + Connection: fmt.Sprintf("%sConnection", node), + Edge: fmt.Sprintf("%sEdge", node), + Node: node, + Order: fmt.Sprintf("%sOrder", node), + OrderField: fmt.Sprintf("%sOrderField", node), }, nil } diff --git a/entgql/template/pagination.tmpl b/entgql/template/pagination.tmpl index 5c26f8815..13007b318 100644 --- a/entgql/template/pagination.tmpl +++ b/entgql/template/pagination.tmpl @@ -231,20 +231,20 @@ const ( {{ $names := nodePaginationNames $node -}} {{ $name := $names.Node -}} -{{ $conn := $names.Conn -}} -{{ $edge := $names.Edge -}} {{- if not (eq $name $node.Name) }} // {{ $name }} is the type alias for {{ $node.Name }}. type {{ $name }} = {{ $node.Name }} {{- end}} +{{ $edge := $names.Edge -}} // {{ $edge }} is the edge representation of {{ $name }}. type {{ $edge }} struct { Node *{{ $name }} `json:"node"` Cursor Cursor `json:"cursor"` } +{{ $conn := $names.Connection -}} // {{ $conn }} is the connection containing edges to {{ $name }}. type {{ $conn }} struct { Edges []*{{ $edge }} `json:"edges"` @@ -257,7 +257,7 @@ type {{ $conn }} struct { // {{ $opt }} enables pagination customization. type {{ $opt }} func(*{{ $pager }}) error -{{ $order := print $name "Order" -}} +{{ $order := $names.Order -}} {{ $optOrder := print "With" $order -}} // {{ $optOrder }} configures pagination ordering. func {{ $optOrder }}(order *{{ $order }}) {{ $opt }} { @@ -441,7 +441,7 @@ func ({{ $r }} *{{ $query }}) Paginate( return conn, nil } -{{ $orderField := print $name "OrderField" -}} +{{ $orderField := $names.OrderField -}} {{- if $orderFields }} var ( {{- range $f := $orderFields }} From 316ca379c27c0766784319d71b35bcc3271c0db7 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 19:19:14 +0000 Subject: [PATCH 13/23] chore: remove autobind, manual mapping for enums MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to our plugin 🎉 --- entgql/internal/todoplugin/gqlgen.yml | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/entgql/internal/todoplugin/gqlgen.yml b/entgql/internal/todoplugin/gqlgen.yml index ee75a4cd3..3f2dca500 100644 --- a/entgql/internal/todoplugin/gqlgen.yml +++ b/entgql/internal/todoplugin/gqlgen.yml @@ -10,11 +10,6 @@ resolver: layout: follow-schema dir: . -autobind: - - entgo.io/contrib/entgql/internal/todoplugin/ent - # Auto-bind the generated `Status` enum to GraphQL. - - entgo.io/contrib/entgql/internal/todoplugin/ent/todo - models: ID: model: @@ -28,22 +23,7 @@ models: UUID: model: - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/uuidgql.UUID - Node: - model: - - entgo.io/contrib/entgql/internal/todoplugin/ent.Noder - # Custom mapping from GraphQL `CategoryStatus` - # to the generated `category.Status` enum type. - CategoryStatus: - model: - - entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status - Role: - model: - - entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role - # Custom mapping from GraphQL `CategoryConfig` and - # `CategoryConfigInput` to `schematype.CategoryConfig`. - CategoryConfig: - model: - - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig + # Custom mapping from GraphQL `CategoryConfigInput` to `schematype.CategoryConfig`. CategoryConfigInput: model: - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig From 9b86d6d065de7ed48a8f892a4f9514b2cd9f4807 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Wed, 2 Mar 2022 21:24:55 +0000 Subject: [PATCH 14/23] chore: updates from code review --- entgql/annotation.go | 3 +-- entgql/internal/todoplugin/ent/entc.go | 12 ------------ entgql/internal/todoplugin/gen.go | 1 - entgql/plugin/plugin.go | 8 ++++---- 4 files changed, 5 insertions(+), 19 deletions(-) delete mode 100644 entgql/internal/todoplugin/ent/entc.go diff --git a/entgql/annotation.go b/entgql/annotation.go index a82abc7ce..f785099e3 100644 --- a/entgql/annotation.go +++ b/entgql/annotation.go @@ -133,8 +133,7 @@ func DecodeAnnotation(annotations gen.Annotations) (*Annotation, error) { return ant, nil } - err := ant.Decode(annotations[ant.Name()]) - if err != nil { + if err := ant.Decode(annotations[ant.Name()]); err != nil { return nil, err } return ant, nil diff --git a/entgql/internal/todoplugin/ent/entc.go b/entgql/internal/todoplugin/ent/entc.go deleted file mode 100644 index 6c5e4a1d7..000000000 --- a/entgql/internal/todoplugin/ent/entc.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019-present Facebook Inc. All rights reserved. -// This source code is licensed under the Apache 2.0 license found -// in the LICENSE file in the root directory of this source tree. - -//go:build ignore -// +build ignore - -package main - -func main() { - -} diff --git a/entgql/internal/todoplugin/gen.go b/entgql/internal/todoplugin/gen.go index 583818b03..fac881ce2 100644 --- a/entgql/internal/todoplugin/gen.go +++ b/entgql/internal/todoplugin/gen.go @@ -14,6 +14,5 @@ package todoplugin -//go:generate go run -mod=mod ./ent/entc.go //go:generate go run -mod=mod ./cmd/entgqlgen.go -path ./ent/schema //go:generate go run -mod=mod github.com/google/addlicense -c Facebook -y 2019-present ./ diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index 5cfbc4cd8..9e51b8138 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -36,8 +36,8 @@ type ( relaySpec bool } - // EntGQLPluginOption is a option for the EntGQL plugin - EntGQLPluginOption func(*EntGQL) error + // EntGQLOption is a option for the EntGQL plugin + EntGQLOption func(*EntGQL) error ) var ( @@ -50,7 +50,7 @@ var ( ) // WithRelaySpecification adds the Relay specification to the schema -func WithRelaySpecification(relaySpec bool) EntGQLPluginOption { +func WithRelaySpecification(relaySpec bool) EntGQLOption { return func(e *EntGQL) error { e.relaySpec = relaySpec return nil @@ -58,7 +58,7 @@ func WithRelaySpecification(relaySpec bool) EntGQLPluginOption { } // NewEntGQLPlugin creates a new EntGQL plugin -func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLPluginOption) (*EntGQL, error) { +func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLOption) (*EntGQL, error) { nodes, err := entgql.FilterNodes(graph.Nodes) if err != nil { return nil, err From 3738db61948e5af66b815a29237ed792952614fd Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 08:13:05 +0000 Subject: [PATCH 15/23] feat: generate GQL objects from Ent schema --- entgql/internal/todoplugin/ent/role/role.go | 39 +- .../internal/todoplugin/entgql.resolvers.go | 41 + entgql/internal/todoplugin/generated.go | 850 +++++++++++++++--- entgql/internal/todoplugin/todo.graphql | 70 +- entgql/internal/todoplugin/todo.resolvers.go | 25 +- entgql/plugin/plugin.go | 39 +- 6 files changed, 819 insertions(+), 245 deletions(-) create mode 100644 entgql/internal/todoplugin/entgql.resolvers.go diff --git a/entgql/internal/todoplugin/ent/role/role.go b/entgql/internal/todoplugin/ent/role/role.go index 90620a357..cf5e06063 100644 --- a/entgql/internal/todoplugin/ent/role/role.go +++ b/entgql/internal/todoplugin/ent/role/role.go @@ -14,7 +14,11 @@ package role -import "io" +import ( + "fmt" + "io" + "strconv" +) type Role string @@ -31,10 +35,35 @@ func (Role) Values() (roles []string) { return } -func (r Role) MarshalGQL(w io.Writer) { - panic("implement me") +func (e Role) String() string { + return string(e) +} + +// Validator is a validator for the "role" field enum values. It is called by the builders before save. +func Validator(e Role) error { + for _, v := range e.Values() { + if v == e.String() { + return nil + } + } + + return fmt.Errorf("role: invalid enum value for role field: %q", e) } -func (r Role) UnmarshalGQL(v interface{}) error { - panic("implement me") +// MarshalGQL implements graphql.Marshaler interface. +func (e Role) MarshalGQL(w io.Writer) { + io.WriteString(w, strconv.Quote(e.String())) +} + +// UnmarshalGQL implements graphql.Unmarshaler interface. +func (e *Role) UnmarshalGQL(val interface{}) error { + str, ok := val.(string) + if !ok { + return fmt.Errorf("enum %T must be a string", val) + } + *e = Role(str) + if err := Validator(*e); err != nil { + return fmt.Errorf("%s is not a valid Role", str) + } + return nil } diff --git a/entgql/internal/todoplugin/entgql.resolvers.go b/entgql/internal/todoplugin/entgql.resolvers.go new file mode 100644 index 000000000..595defffb --- /dev/null +++ b/entgql/internal/todoplugin/entgql.resolvers.go @@ -0,0 +1,41 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package todoplugin + +// 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. + +import ( + "context" + + "entgo.io/contrib/entgql/internal/todoplugin/ent" +) + +func (r *masterUserResolver) Age(ctx context.Context, obj *ent.User) (float64, error) { + return float64(obj.Age), nil +} + +func (r *masterUserResolver) Amount(ctx context.Context, obj *ent.User) (float64, error) { + return float64(obj.Amount), nil +} + +// MasterUser returns MasterUserResolver implementation. +func (r *Resolver) MasterUser() MasterUserResolver { return &masterUserResolver{r} } + +// Todo returns TodoResolver implementation. +func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } + +type masterUserResolver struct{ *Resolver } +type todoResolver struct{ *Resolver } diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go index 52702a930..6a2dda53c 100644 --- a/entgql/internal/todoplugin/generated.go +++ b/entgql/internal/todoplugin/generated.go @@ -69,12 +69,24 @@ type ComplexityRoot struct { MaxMembers func(childComplexity int) int } + CategoryConnection struct { + Edges func(childComplexity int) int + PageInfo func(childComplexity int) int + TotalCount func(childComplexity int) int + } + + CategoryEdge struct { + Cursor func(childComplexity int) int + Node func(childComplexity int) int + } + MasterUser struct { - Age func(childComplexity int) int - Amount func(childComplexity int) int - ID func(childComplexity int) int - Role func(childComplexity int) int - Username func(childComplexity int) int + Age func(childComplexity int) int + Amount func(childComplexity int) int + ID func(childComplexity int) int + NullableString func(childComplexity int) int + Role func(childComplexity int) int + Username func(childComplexity int) int } MasterUserConnection struct { @@ -107,14 +119,15 @@ type ComplexityRoot struct { } Todo struct { - Category func(childComplexity int) int - Children func(childComplexity int) int - CreatedAt func(childComplexity int) int - ID func(childComplexity int) int - Parent func(childComplexity int) int - Priority func(childComplexity int) int - Status func(childComplexity int) int - Text func(childComplexity int) int + Category func(childComplexity int) int + Children func(childComplexity int) int + CreatedAt func(childComplexity int) int + ID func(childComplexity int) int + Parent func(childComplexity int) int + Priority func(childComplexity int) int + Status func(childComplexity int) int + Text func(childComplexity int) int + VisibilityStatus func(childComplexity int) int } TodoConnection struct { @@ -217,6 +230,41 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.CategoryConfig.MaxMembers(childComplexity), true + case "CategoryConnection.edges": + if e.complexity.CategoryConnection.Edges == nil { + break + } + + return e.complexity.CategoryConnection.Edges(childComplexity), true + + case "CategoryConnection.pageInfo": + if e.complexity.CategoryConnection.PageInfo == nil { + break + } + + return e.complexity.CategoryConnection.PageInfo(childComplexity), true + + case "CategoryConnection.totalCount": + if e.complexity.CategoryConnection.TotalCount == nil { + break + } + + return e.complexity.CategoryConnection.TotalCount(childComplexity), true + + case "CategoryEdge.cursor": + if e.complexity.CategoryEdge.Cursor == nil { + break + } + + return e.complexity.CategoryEdge.Cursor(childComplexity), true + + case "CategoryEdge.node": + if e.complexity.CategoryEdge.Node == nil { + break + } + + return e.complexity.CategoryEdge.Node(childComplexity), true + case "MasterUser.age": if e.complexity.MasterUser.Age == nil { break @@ -238,6 +286,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MasterUser.ID(childComplexity), true + case "MasterUser.nullableString": + if e.complexity.MasterUser.NullableString == nil { + break + } + + return e.complexity.MasterUser.NullableString(childComplexity), true + case "MasterUser.role": if e.complexity.MasterUser.Role == nil { break @@ -426,6 +481,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Todo.Text(childComplexity), true + case "Todo.visibilityStatus": + if e.complexity.Todo.VisibilityStatus == nil { + break + } + + return e.complexity.Todo.VisibilityStatus(childComplexity), true + case "TodoConnection.edges": if e.complexity.TodoConnection.Edges == nil { break @@ -530,10 +592,6 @@ var sources = []*ast.Source{ boolArg: Boolean ) on OBJECT | INPUT_OBJECT | SCALAR | FIELD_DEFINITION -interface Node { - id: ID! -} - type CategoryConfig { maxMembers: Int } @@ -557,26 +615,10 @@ scalar Duration scalar Uint64 scalar UUID -type Todo implements Node { - id: ID! - createdAt: Time - status: Status! - priority: Int! - text: String! - parent: Todo - children: [Todo!] +extend type Todo { category: Category -} - -type Category implements Node { - id: ID! - text: String! - uuidA: UUID - status: CategoryStatus! - config: CategoryConfig! - duration: Duration! - count: Uint64! - # strings: [String] + children: [Todo!] + parent: Todo } input TodoInput { @@ -587,26 +629,6 @@ input TodoInput { category_id: ID } -scalar Cursor - -type PageInfo { - hasNextPage: Boolean! - hasPreviousPage: Boolean! - startCursor: Cursor - endCursor: Cursor -} - -type TodoConnection { - totalCount: Int! - pageInfo: PageInfo! - edges: [TodoEdge] -} - -type TodoEdge { - node: Todo - cursor: Cursor! -} - enum OrderDirection { ASC DESC @@ -624,31 +646,17 @@ input TodoOrder { field: TodoOrderField } +enum VisibilityStatus { + LISTING + HIDDEN +} + enum Role { ADMIN USER UNKNOWN } -type MasterUser implements Node { - id: ID! - username: String! - age: Float! - amount: Float! - role: Role! -} - -type MasterUserConnection { - totalCount: Int! - pageInfo: PageInfo! - edges: [MasterUserEdge] -} - -type MasterUserEdge { - node: MasterUser - cursor: Cursor! -} - type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! @@ -665,6 +673,150 @@ type Mutation { createTodo(todo: TodoInput!): Todo! clearTodos: Int! } +`, BuiltIn: false}, + {Name: "entgql.graphql", Input: `type Category implements Node { + id: ID! + text: String! + uuidA: UUID + status: CategoryStatus! + config: CategoryConfig! + duration: Duration! + count: Uint64! +} +""" +A connection to a list of items. +""" +type CategoryConnection { + """ + A list of edges. + """ + edges: [CategoryEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type CategoryEdge { + """ + The item at the end of the edge. + """ + node: Category + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} +""" +Define a Relay Cursor type: +https://relay.dev/graphql/connections.htm#sec-Cursor +""" +scalar Cursor +type MasterUser implements Node { + id: ID! + username: String! + age: Float! + amount: Float! + role: Role! + nullableString: String +} +""" +A connection to a list of items. +""" +type MasterUserConnection { + """ + A list of edges. + """ + edges: [MasterUserEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type MasterUserEdge { + """ + The item at the end of the edge. + """ + node: MasterUser + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} +""" +An object with an ID. +Follows the [Relay Global Object Identification Specification](https://relay.dev/graphql/objectidentification.htm) +""" +interface Node { + """ + The id of the object. + """ + id: ID! +} +""" +Information about pagination in a connection. +https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo +""" +type PageInfo { + """ + When paginating forwards, are there more items? + """ + hasNextPage: Boolean! + """ + When paginating backwards, are there more items? + """ + hasPreviousPage: Boolean! + """ + When paginating backwards, the cursor to continue. + """ + startCursor: Cursor + """ + When paginating forwards, the cursor to continue. + """ + endCursor: Cursor +} +type Todo implements Node { + id: ID! + createdAt: Time! + visibilityStatus: VisibilityStatus! + status: Status! + priority: Int! + text: String! +} +""" +A connection to a list of items. +""" +type TodoConnection { + """ + A list of edges. + """ + edges: [TodoEdge] + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! + totalCount: Int! +} +""" +An edge in a connection. +""" +type TodoEdge { + """ + The item at the end of the edge. + """ + node: Todo + """ + A cursor for use in pagination. + """ + cursor: Cursor! +} `, BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -1135,6 +1287,175 @@ func (ec *executionContext) _CategoryConfig_maxMembers(ctx context.Context, fiel return ec.marshalOInt2int(ctx, field.Selections, res) } +func (ec *executionContext) _CategoryConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.CategoryConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CategoryConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Edges, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*ent.CategoryEdge) + fc.Result = res + return ec.marshalOCategoryEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryEdge(ctx, field.Selections, res) +} + +func (ec *executionContext) _CategoryConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.CategoryConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CategoryConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PageInfo, 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.(ent.PageInfo) + fc.Result = res + return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) +} + +func (ec *executionContext) _CategoryConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.CategoryConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CategoryConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.TotalCount, 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.(int) + fc.Result = res + return ec.marshalNInt2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _CategoryEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.CategoryEdge) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CategoryEdge", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Node, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.Category) + fc.Result = res + return ec.marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx, field.Selections, res) +} + +func (ec *executionContext) _CategoryEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *ent.CategoryEdge) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "CategoryEdge", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Cursor, 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.(ent.Cursor) + fc.Result = res + return ec.marshalNCursor2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx, field.Selections, res) +} + func (ec *executionContext) _MasterUser_id(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -1310,7 +1631,7 @@ func (ec *executionContext) _MasterUser_role(ctx context.Context, field graphql. return ec.marshalNRole2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋroleᚐRole(ctx, field.Selections, res) } -func (ec *executionContext) _MasterUserConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUser_nullableString(ctx context.Context, field graphql.CollectedField, obj *ent.User) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1318,7 +1639,7 @@ func (ec *executionContext) _MasterUserConnection_totalCount(ctx context.Context } }() fc := &graphql.FieldContext{ - Object: "MasterUserConnection", + Object: "MasterUser", Field: field, Args: nil, IsMethod: false, @@ -1328,21 +1649,50 @@ func (ec *executionContext) _MasterUserConnection_totalCount(ctx context.Context ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalCount, nil + return obj.NullableString, 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.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _MasterUserConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null } + }() + fc := &graphql.FieldContext{ + Object: "MasterUserConnection", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Edges, nil + }) + if err != nil { + ec.Error(ctx, err) return graphql.Null } - res := resTmp.(int) + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*ent.MasterUserEdge) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalOMasterUserEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐMasterUserEdge(ctx, field.Selections, res) } func (ec *executionContext) _MasterUserConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { @@ -1380,7 +1730,7 @@ func (ec *executionContext) _MasterUserConnection_pageInfo(ctx context.Context, return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _MasterUserConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _MasterUserConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1398,18 +1748,21 @@ func (ec *executionContext) _MasterUserConnection_edges(ctx context.Context, fie ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edges, nil + return obj.TotalCount, 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.([]*ent.MasterUserEdge) + res := resTmp.(int) fc.Result = res - return ec.marshalOMasterUserEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐMasterUserEdge(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } func (ec *executionContext) _MasterUserEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.MasterUserEdge) (ret graphql.Marshaler) { @@ -1913,10 +2266,45 @@ func (ec *executionContext) _Todo_id(ctx context.Context, field graphql.Collecte } res := resTmp.(int) fc.Result = res - return ec.marshalNID2int(ctx, field.Selections, res) + return ec.marshalNID2int(ctx, field.Selections, res) +} + +func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Todo", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.CreatedAt, 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.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_visibilityStatus(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -1934,18 +2322,21 @@ func (ec *executionContext) _Todo_createdAt(ctx context.Context, field graphql.C ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.CreatedAt, nil + return obj.VisibilityStatus, 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.(time.Time) + res := resTmp.(todo.VisibilityStatus) fc.Result = res - return ec.marshalOTime2timeᚐTime(ctx, field.Selections, res) + return ec.marshalNVisibilityStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐVisibilityStatus(ctx, field.Selections, res) } func (ec *executionContext) _Todo_status(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { @@ -2053,7 +2444,7 @@ func (ec *executionContext) _Todo_text(ctx context.Context, field graphql.Collec return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2065,13 +2456,13 @@ func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.Coll Field: field, Args: nil, IsMethod: true, - IsResolver: false, + IsResolver: true, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Parent(ctx) + return ec.resolvers.Todo().Category(rctx, obj) }) if err != nil { ec.Error(ctx, err) @@ -2080,9 +2471,9 @@ func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.Coll if resTmp == nil { return graphql.Null } - res := resTmp.(*ent.Todo) + res := resTmp.(*ent.Category) fc.Result = res - return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) + return ec.marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx, field.Selections, res) } func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { @@ -2117,7 +2508,7 @@ func (ec *executionContext) _Todo_children(ctx context.Context, field graphql.Co return ec.marshalOTodo2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoᚄ(ctx, field.Selections, res) } -func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { +func (ec *executionContext) _Todo_parent(ctx context.Context, field graphql.CollectedField, obj *ent.Todo) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2129,13 +2520,13 @@ func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.Co Field: field, Args: nil, IsMethod: true, - IsResolver: true, + IsResolver: false, } ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Todo().Category(rctx, obj) + return obj.Parent(ctx) }) if err != nil { ec.Error(ctx, err) @@ -2144,12 +2535,12 @@ func (ec *executionContext) _Todo_category(ctx context.Context, field graphql.Co if resTmp == nil { return graphql.Null } - res := resTmp.(*ent.Category) + res := resTmp.(*ent.Todo) fc.Result = res - return ec.marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategory(ctx, field.Selections, res) + return ec.marshalOTodo2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx, field.Selections, res) } -func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2167,21 +2558,18 @@ func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, fiel ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.TotalCount, nil + return obj.Edges, 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.(int) + res := resTmp.([]*ent.TodoEdge) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalOTodoEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx, field.Selections, res) } func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { @@ -2219,7 +2607,7 @@ func (ec *executionContext) _TodoConnection_pageInfo(ctx context.Context, field return ec.marshalNPageInfo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { +func (ec *executionContext) _TodoConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *ent.TodoConnection) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { ec.Error(ctx, ec.Recover(ctx, r)) @@ -2237,18 +2625,21 @@ func (ec *executionContext) _TodoConnection_edges(ctx context.Context, field gra ctx = graphql.WithFieldContext(ctx, fc) resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Edges, nil + return obj.TotalCount, 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.([]*ent.TodoEdge) + res := resTmp.(int) fc.Result = res - return ec.marshalOTodoEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoEdge(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } func (ec *executionContext) _TodoEdge_node(ctx context.Context, field graphql.CollectedField, obj *ent.TodoEdge) (ret graphql.Marshaler) { @@ -3568,11 +3959,6 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj switch obj := (obj).(type) { case nil: return graphql.Null - case *ent.Todo: - if obj == nil { - return graphql.Null - } - return ec._Todo(ctx, sel, obj) case *ent.Category: if obj == nil { return graphql.Null @@ -3583,6 +3969,11 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._MasterUser(ctx, sel, obj) + case *ent.Todo: + if obj == nil { + return graphql.Null + } + return ec._Todo(ctx, sel, obj) default: panic(fmt.Errorf("unexpected type %T", obj)) } @@ -3708,6 +4099,92 @@ func (ec *executionContext) _CategoryConfig(ctx context.Context, sel ast.Selecti return out } +var categoryConnectionImplementors = []string{"CategoryConnection"} + +func (ec *executionContext) _CategoryConnection(ctx context.Context, sel ast.SelectionSet, obj *ent.CategoryConnection) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, categoryConnectionImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("CategoryConnection") + case "edges": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryConnection_edges(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "pageInfo": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryConnection_pageInfo(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + case "totalCount": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryConnection_totalCount(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var categoryEdgeImplementors = []string{"CategoryEdge"} + +func (ec *executionContext) _CategoryEdge(ctx context.Context, sel ast.SelectionSet, obj *ent.CategoryEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, categoryEdgeImplementors) + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("CategoryEdge") + case "node": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryEdge_node(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + case "cursor": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._CategoryEdge_cursor(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var masterUserImplementors = []string{"MasterUser", "Node"} func (ec *executionContext) _MasterUser(ctx context.Context, sel ast.SelectionSet, obj *ent.User) graphql.Marshaler { @@ -3788,6 +4265,13 @@ func (ec *executionContext) _MasterUser(ctx context.Context, sel ast.SelectionSe if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } + case "nullableString": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._MasterUser_nullableString(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -3809,16 +4293,13 @@ func (ec *executionContext) _MasterUserConnection(ctx context.Context, sel ast.S switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("MasterUserConnection") - case "totalCount": + case "edges": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._MasterUserConnection_totalCount(ctx, field, obj) + return ec._MasterUserConnection_edges(ctx, field, obj) } out.Values[i] = innerFunc(ctx) - if out.Values[i] == graphql.Null { - invalids++ - } case "pageInfo": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { return ec._MasterUserConnection_pageInfo(ctx, field, obj) @@ -3829,13 +4310,16 @@ func (ec *executionContext) _MasterUserConnection(ctx context.Context, sel ast.S if out.Values[i] == graphql.Null { invalids++ } - case "edges": + case "totalCount": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._MasterUserConnection_edges(ctx, field, obj) + return ec._MasterUserConnection_totalCount(ctx, field, obj) } out.Values[i] = innerFunc(ctx) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -4124,6 +4608,19 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj out.Values[i] = innerFunc(ctx) + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + case "visibilityStatus": + innerFunc := func(ctx context.Context) (res graphql.Marshaler) { + return ec._Todo_visibilityStatus(ctx, field, obj) + } + + out.Values[i] = innerFunc(ctx) + + if out.Values[i] == graphql.Null { + atomic.AddUint32(&invalids, 1) + } case "status": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { return ec._Todo_status(ctx, field, obj) @@ -4154,7 +4651,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { atomic.AddUint32(&invalids, 1) } - case "parent": + case "category": field := field innerFunc := func(ctx context.Context) (res graphql.Marshaler) { @@ -4163,7 +4660,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Todo_parent(ctx, field, obj) + res = ec._Todo_category(ctx, field, obj) return res } @@ -4188,7 +4685,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj return innerFunc(ctx) }) - case "category": + case "parent": field := field innerFunc := func(ctx context.Context) (res graphql.Marshaler) { @@ -4197,7 +4694,7 @@ func (ec *executionContext) _Todo(ctx context.Context, sel ast.SelectionSet, obj ec.Error(ctx, ec.Recover(ctx, r)) } }() - res = ec._Todo_category(ctx, field, obj) + res = ec._Todo_parent(ctx, field, obj) return res } @@ -4226,16 +4723,13 @@ func (ec *executionContext) _TodoConnection(ctx context.Context, sel ast.Selecti switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("TodoConnection") - case "totalCount": + case "edges": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._TodoConnection_totalCount(ctx, field, obj) + return ec._TodoConnection_edges(ctx, field, obj) } out.Values[i] = innerFunc(ctx) - if out.Values[i] == graphql.Null { - invalids++ - } case "pageInfo": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { return ec._TodoConnection_pageInfo(ctx, field, obj) @@ -4246,13 +4740,16 @@ func (ec *executionContext) _TodoConnection(ctx context.Context, sel ast.Selecti if out.Values[i] == graphql.Null { invalids++ } - case "edges": + case "totalCount": innerFunc := func(ctx context.Context) (res graphql.Marshaler) { - return ec._TodoConnection_edges(ctx, field, obj) + return ec._TodoConnection_totalCount(ctx, field, obj) } out.Values[i] = innerFunc(ctx) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -4935,6 +5432,21 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S return res } +func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { + res, err := graphql.UnmarshalTime(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { + res := graphql.MarshalTime(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + func (ec *executionContext) marshalNTodo2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodo(ctx context.Context, sel ast.SelectionSet, v ent.Todo) graphql.Marshaler { return ec._Todo(ctx, sel, &v) } @@ -4969,6 +5481,16 @@ func (ec *executionContext) marshalNUint642uint64(ctx context.Context, sel ast.S return res } +func (ec *executionContext) unmarshalNVisibilityStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐVisibilityStatus(ctx context.Context, v interface{}) (todo.VisibilityStatus, error) { + var res todo.VisibilityStatus + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNVisibilityStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋtodoᚐVisibilityStatus(ctx context.Context, sel ast.SelectionSet, v todo.VisibilityStatus) graphql.Marshaler { + return v +} + func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { return ec.___Directive(ctx, sel, &v) } @@ -5255,6 +5777,54 @@ func (ec *executionContext) marshalOCategory2ᚖentgoᚗioᚋcontribᚋentgqlᚋ return ec._Category(ctx, sel, v) } +func (ec *executionContext) marshalOCategoryEdge2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryEdge(ctx context.Context, sel ast.SelectionSet, v []*ent.CategoryEdge) 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.marshalOCategoryEdge2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + return ret +} + +func (ec *executionContext) marshalOCategoryEdge2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryEdge(ctx context.Context, sel ast.SelectionSet, v *ent.CategoryEdge) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._CategoryEdge(ctx, sel, v) +} + func (ec *executionContext) unmarshalOCursor2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCursor(ctx context.Context, v interface{}) (*ent.Cursor, error) { if v == nil { return nil, nil @@ -5401,16 +5971,6 @@ func (ec *executionContext) marshalOString2ᚖstring(ctx context.Context, sel as return res } -func (ec *executionContext) unmarshalOTime2timeᚐTime(ctx context.Context, v interface{}) (time.Time, error) { - res, err := graphql.UnmarshalTime(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalOTime2timeᚐTime(ctx context.Context, sel ast.SelectionSet, v time.Time) graphql.Marshaler { - res := graphql.MarshalTime(v) - return res -} - func (ec *executionContext) marshalOTodo2ᚕᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoᚄ(ctx context.Context, sel ast.SelectionSet, v []*ent.Todo) graphql.Marshaler { if v == nil { return graphql.Null diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql index 71c68c449..d8120560b 100644 --- a/entgql/internal/todoplugin/todo.graphql +++ b/entgql/internal/todoplugin/todo.graphql @@ -3,10 +3,6 @@ directive @someDirective( boolArg: Boolean ) on OBJECT | INPUT_OBJECT | SCALAR | FIELD_DEFINITION -interface Node { - id: ID! -} - type CategoryConfig { maxMembers: Int } @@ -30,26 +26,10 @@ scalar Duration scalar Uint64 scalar UUID -type Todo implements Node { - id: ID! - createdAt: Time - status: Status! - priority: Int! - text: String! - parent: Todo - children: [Todo!] +extend type Todo { category: Category -} - -type Category implements Node { - id: ID! - text: String! - uuidA: UUID - status: CategoryStatus! - config: CategoryConfig! - duration: Duration! - count: Uint64! - # strings: [String] + children: [Todo!] + parent: Todo } input TodoInput { @@ -60,26 +40,6 @@ input TodoInput { category_id: ID } -scalar Cursor - -type PageInfo { - hasNextPage: Boolean! - hasPreviousPage: Boolean! - startCursor: Cursor - endCursor: Cursor -} - -type TodoConnection { - totalCount: Int! - pageInfo: PageInfo! - edges: [TodoEdge] -} - -type TodoEdge { - node: Todo - cursor: Cursor! -} - enum OrderDirection { ASC DESC @@ -97,31 +57,17 @@ input TodoOrder { field: TodoOrderField } +enum VisibilityStatus { + LISTING + HIDDEN +} + enum Role { ADMIN USER UNKNOWN } -type MasterUser implements Node { - id: ID! - username: String! - age: Float! - amount: Float! - role: Role! -} - -type MasterUserConnection { - totalCount: Int! - pageInfo: PageInfo! - edges: [MasterUserEdge] -} - -type MasterUserEdge { - node: MasterUser - cursor: Cursor! -} - type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! diff --git a/entgql/internal/todoplugin/todo.resolvers.go b/entgql/internal/todoplugin/todo.resolvers.go index d0167ac9a..426c217f5 100644 --- a/entgql/internal/todoplugin/todo.resolvers.go +++ b/entgql/internal/todoplugin/todo.resolvers.go @@ -19,19 +19,12 @@ package todoplugin import ( "context" - "fmt" "entgo.io/contrib/entgql/internal/todoplugin/ent" + "entgo.io/contrib/entgql/internal/todoplugin/ent/category" + "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" ) -func (r *masterUserResolver) Age(ctx context.Context, obj *ent.User) (float64, error) { - return float64(obj.Age), nil -} - -func (r *masterUserResolver) Amount(ctx context.Context, obj *ent.User) (float64, error) { - return float64(obj.Amount), nil -} - func (r *mutationResolver) CreateTodo(ctx context.Context, todo TodoInput) (*ent.Todo, error) { client := ent.FromContext(ctx) return client.Todo. @@ -66,22 +59,18 @@ func (r *queryResolver) Todos(ctx context.Context, after *ent.Cursor, first *int } func (r *todoResolver) Category(ctx context.Context, obj *ent.Todo) (*ent.Category, error) { - panic(fmt.Errorf("not implemented")) + e, err := r.client.Category. + Query(). + Where(category.HasTodosWith(todo.ID(obj.ID))). + First(ctx) + return e, ent.MaskNotFound(err) } -// MasterUser returns MasterUserResolver implementation. -func (r *Resolver) MasterUser() MasterUserResolver { return &masterUserResolver{r} } - // Mutation returns MutationResolver implementation. func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} } // Query returns QueryResolver implementation. func (r *Resolver) Query() QueryResolver { return &queryResolver{r} } -// Todo returns TodoResolver implementation. -func (r *Resolver) Todo() TodoResolver { return &todoResolver{r} } - -type masterUserResolver struct{ *Resolver } type mutationResolver struct{ *Resolver } type queryResolver struct{ *Resolver } -type todoResolver struct{ *Resolver } diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index 9e51b8138..8a1602230 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -29,10 +29,9 @@ import ( type ( // EntGQL is a plugin that generates GQL schema from the Ent's Graph EntGQL struct { - graph *gen.Graph - nodes []*gen.Type - schema *ast.Schema - + graph *gen.Graph + nodes []*gen.Type + schema *ast.Schema relaySpec bool } @@ -74,14 +73,11 @@ func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLOption) (*EntGQL, error) { } } - types, err := e.buildTypes() + e.schema, err = e.prepareSchema() if err != nil { - return nil, err + return nil, fmt.Errorf("entgql: failed to prepare the GQL schema: %w", err) } - e.schema = &ast.Schema{ - Types: types, - } return e, nil } @@ -92,12 +88,25 @@ func (*EntGQL) Name() string { // InjectSourceEarly implements the EarlySourceInjector interface. func (e *EntGQL) InjectSourceEarly() *ast.Source { - return nil - // return &ast.Source{ - // Name: "entgql.graphql", - // Input: printSchema(e.schema), - // BuiltIn: false, - // } + return &ast.Source{ + Name: "entgql.graphql", + Input: printSchema(e.schema), + BuiltIn: false, + } +} + +func (e *EntGQL) prepareSchema() (*ast.Schema, error) { + types, err := e.buildTypes() + if err != nil { + return nil, err + } + if e.relaySpec { + insertDefinitions(types, relayBuiltinTypes()...) + } + + return &ast.Schema{ + Types: types, + }, nil } func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { From a7c716f54afb48f9c4aa1aed72631be4319cc3c5 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 08:17:07 +0000 Subject: [PATCH 16/23] fix: fixed lint --- entgql/internal/todoplugin/ent/role/role.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/entgql/internal/todoplugin/ent/role/role.go b/entgql/internal/todoplugin/ent/role/role.go index cf5e06063..58cad37db 100644 --- a/entgql/internal/todoplugin/ent/role/role.go +++ b/entgql/internal/todoplugin/ent/role/role.go @@ -52,7 +52,7 @@ func Validator(e Role) error { // MarshalGQL implements graphql.Marshaler interface. func (e Role) MarshalGQL(w io.Writer) { - io.WriteString(w, strconv.Quote(e.String())) + _, _ = io.WriteString(w, strconv.Quote(e.String())) } // UnmarshalGQL implements graphql.Unmarshaler interface. From ee74e9964dd841a447a869faaf6ef0703dedc02c Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 11:20:01 +0000 Subject: [PATCH 17/23] fix: support GoType for enum field --- entgql/plugin/plugin_config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/entgql/plugin/plugin_config.go b/entgql/plugin/plugin_config.go index 5e060afdc..cc0107484 100644 --- a/entgql/plugin/plugin_config.go +++ b/entgql/plugin/plugin_config.go @@ -70,10 +70,10 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { goType := "" switch { + case field.IsOther() || (field.IsEnum() && field.HasGoType()): + goType = fmt.Sprintf("%s.%s", field.Type.RType.PkgPath, field.Type.RType.Name) case field.IsEnum(): goType = fmt.Sprintf("%s/%s", e.graph.Package, field.Type.Ident) - case field.IsOther(): - goType = fmt.Sprintf("%s.%s", field.Type.RType.PkgPath, field.Type.RType.Name) default: continue } From 48daee310bc1b669a19dcb411c9e440c90220a2e Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 11:22:53 +0000 Subject: [PATCH 18/23] fix: fixed exitcode for codegen --- entgql/internal/todoplugin/cmd/entgqlgen.go | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/entgql/internal/todoplugin/cmd/entgqlgen.go b/entgql/internal/todoplugin/cmd/entgqlgen.go index c1856c6d2..71bebb18b 100644 --- a/entgql/internal/todoplugin/cmd/entgqlgen.go +++ b/entgql/internal/todoplugin/cmd/entgqlgen.go @@ -16,9 +16,7 @@ package main import ( "flag" - "fmt" "log" - "os" "entgo.io/contrib/entgql" "entgo.io/contrib/entgql/plugin" @@ -44,15 +42,14 @@ func main() { cfg, err := config.LoadConfigFromDefaultLocations() if err != nil { - fmt.Fprintln(os.Stderr, "failed to load config", err.Error()) - os.Exit(2) + log.Fatalf("failed to load config %v", err) } entgqlPlugin, err := plugin.NewEntGQLPlugin(graph, plugin.WithRelaySpecification(true), ) if err != nil { - log.Fatalf("creating entgql plugin: %v", err) + log.Fatalf("failed to create entgql plugin: %v", err) } ex, err := entgql.NewExtension() @@ -81,15 +78,9 @@ func main() { if err != nil { log.Fatalf("running ent codegen: %v", err) } + + err = api.Generate(cfg, api.PrependPlugin(entgqlPlugin)) if err != nil { - fmt.Fprintln(os.Stderr, "failed to create entgql plugin", err.Error()) - os.Exit(2) - } - err = api.Generate(cfg, - api.PrependPlugin(entgqlPlugin), - ) - if err != nil { - fmt.Fprintln(os.Stderr, err.Error()) - os.Exit(3) + log.Fatalf("running gqlgen: %v", err) } } From 21e56ba00ba34e43db5b0ec00ec20cc15dc149de Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 11:35:01 +0000 Subject: [PATCH 19/23] chore: cleanup ent schema --- entgql/internal/todoplugin/ent/category.go | 2 +- .../internal/todoplugin/ent/category/where.go | 2 +- .../todoplugin/ent/category_create.go | 2 +- .../todoplugin/ent/category_update.go | 2 +- .../todoplugin/ent/gql_where_input.go | 2 +- entgql/internal/todoplugin/ent/mutation.go | 2 +- .../todoplugin/ent/schema/category.go | 2 +- .../ent/schema/durationgql/durationgql.go | 48 ------------------- .../ent/schema/schematype/schematype.go | 40 ---------------- .../todoplugin/ent/schema/uuidgql/uuidgql.go | 38 --------------- entgql/internal/todoplugin/generated.go | 42 +++------------- entgql/internal/todoplugin/gqlgen.yml | 10 ++-- entgql/internal/todoplugin/resolver.go | 10 +--- entgql/internal/todoplugin/todo.graphql | 5 -- entgql/plugin/plugin_config_test.go | 4 +- 15 files changed, 22 insertions(+), 189 deletions(-) delete mode 100644 entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go delete mode 100644 entgql/internal/todoplugin/ent/schema/schematype/schematype.go delete mode 100644 entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go diff --git a/entgql/internal/todoplugin/ent/category.go b/entgql/internal/todoplugin/ent/category.go index e52f533b2..01e4dc105 100644 --- a/entgql/internal/todoplugin/ent/category.go +++ b/entgql/internal/todoplugin/ent/category.go @@ -21,8 +21,8 @@ import ( "strings" "time" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/category" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/ent/dialect/sql" "github.com/google/uuid" ) diff --git a/entgql/internal/todoplugin/ent/category/where.go b/entgql/internal/todoplugin/ent/category/where.go index 04c3eb03b..266a62058 100644 --- a/entgql/internal/todoplugin/ent/category/where.go +++ b/entgql/internal/todoplugin/ent/category/where.go @@ -19,8 +19,8 @@ package category import ( "time" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" "github.com/google/uuid" diff --git a/entgql/internal/todoplugin/ent/category_create.go b/entgql/internal/todoplugin/ent/category_create.go index a75eb08b7..22cef8eac 100644 --- a/entgql/internal/todoplugin/ent/category_create.go +++ b/entgql/internal/todoplugin/ent/category_create.go @@ -22,8 +22,8 @@ import ( "fmt" "time" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/category" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "entgo.io/ent/dialect/sql/sqlgraph" "entgo.io/ent/schema/field" diff --git a/entgql/internal/todoplugin/ent/category_update.go b/entgql/internal/todoplugin/ent/category_update.go index ce0c52524..3da8a5066 100644 --- a/entgql/internal/todoplugin/ent/category_update.go +++ b/entgql/internal/todoplugin/ent/category_update.go @@ -22,9 +22,9 @@ import ( "fmt" "time" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/category" "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "entgo.io/ent/dialect/sql" "entgo.io/ent/dialect/sql/sqlgraph" diff --git a/entgql/internal/todoplugin/ent/gql_where_input.go b/entgql/internal/todoplugin/ent/gql_where_input.go index 2bf9d0fd7..188e861d5 100644 --- a/entgql/internal/todoplugin/ent/gql_where_input.go +++ b/entgql/internal/todoplugin/ent/gql_where_input.go @@ -24,7 +24,7 @@ import ( "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" "entgo.io/contrib/entgql/internal/todoplugin/ent/role" "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "entgo.io/contrib/entgql/internal/todoplugin/ent/user" ) diff --git a/entgql/internal/todoplugin/ent/mutation.go b/entgql/internal/todoplugin/ent/mutation.go index 1bef8836c..595e89718 100644 --- a/entgql/internal/todoplugin/ent/mutation.go +++ b/entgql/internal/todoplugin/ent/mutation.go @@ -23,11 +23,11 @@ import ( "sync" "time" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/category" "entgo.io/contrib/entgql/internal/todoplugin/ent/predicate" "entgo.io/contrib/entgql/internal/todoplugin/ent/role" "entgo.io/contrib/entgql/internal/todoplugin/ent/schema" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" "entgo.io/contrib/entgql/internal/todoplugin/ent/user" "github.com/google/uuid" diff --git a/entgql/internal/todoplugin/ent/schema/category.go b/entgql/internal/todoplugin/ent/schema/category.go index f58d583ea..921f96b47 100644 --- a/entgql/internal/todoplugin/ent/schema/category.go +++ b/entgql/internal/todoplugin/ent/schema/category.go @@ -25,7 +25,7 @@ import ( "entgo.io/ent/schema/field" "github.com/google/uuid" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" ) // Category holds the schema definition for the Category entity. diff --git a/entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go b/entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go deleted file mode 100644 index 1c150a0b5..000000000 --- a/entgql/internal/todoplugin/ent/schema/durationgql/durationgql.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019-present Facebook -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package durationgql - -import ( - "encoding/json" - "fmt" - "io" - "strconv" - "time" - - "github.com/99designs/gqlgen/graphql" -) - -func MarshalDuration(t time.Duration) graphql.Marshaler { - return graphql.WriterFunc(func(w io.Writer) { - _, _ = io.WriteString(w, strconv.FormatInt(int64(t), 10)) - }) -} - -func UnmarshalDuration(v interface{}) (time.Duration, error) { - switch v := v.(type) { - case int64: - return time.Duration(v), nil - case string: - return time.ParseDuration(v) - case json.Number: - i, err := v.Int64() - if err != nil { - return 0, err - } - return time.Duration(i), nil - default: - return 0, fmt.Errorf("invalid type %T, expect string", v) - } -} diff --git a/entgql/internal/todoplugin/ent/schema/schematype/schematype.go b/entgql/internal/todoplugin/ent/schema/schematype/schematype.go deleted file mode 100644 index 413fc5d03..000000000 --- a/entgql/internal/todoplugin/ent/schema/schematype/schematype.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019-present Facebook -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package schematype provides custom types for ent/schema. -package schematype - -import ( - "database/sql/driver" - "encoding/json" -) - -// CategoryConfig implements the field.ValueScanner interface. -type CategoryConfig struct { - MaxMembers int `json:"maxMembers,omitempty"` -} - -func (t *CategoryConfig) Scan(v interface{}) (err error) { - switch v := v.(type) { - case string: - err = json.Unmarshal([]byte(v), t) - case []byte: - err = json.Unmarshal(v, t) - } - return -} - -func (t *CategoryConfig) Value() (driver.Value, error) { - return json.Marshal(t) -} diff --git a/entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go b/entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go deleted file mode 100644 index e19de6d33..000000000 --- a/entgql/internal/todoplugin/ent/schema/uuidgql/uuidgql.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2019-present Facebook -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package uuidgql - -import ( - "fmt" - "io" - "strconv" - - "github.com/99designs/gqlgen/graphql" - "github.com/google/uuid" -) - -func MarshalUUID(u uuid.UUID) graphql.Marshaler { - return graphql.WriterFunc(func(w io.Writer) { - _, _ = io.WriteString(w, strconv.Quote(u.String())) - }) -} - -func UnmarshalUUID(v interface{}) (u uuid.UUID, err error) { - s, ok := v.(string) - if !ok { - return u, fmt.Errorf("invalid type %T, expect string", v) - } - return uuid.Parse(s) -} diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go index 6a2dda53c..aeb8546c5 100644 --- a/entgql/internal/todoplugin/generated.go +++ b/entgql/internal/todoplugin/generated.go @@ -12,13 +12,13 @@ import ( "sync/atomic" "time" + "entgo.io/contrib/entgql/internal/todo/ent/schema/durationgql" + "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype" "entgo.io/contrib/entgql/internal/todoplugin/ent" "entgo.io/contrib/entgql/internal/todoplugin/ent/category" "entgo.io/contrib/entgql/internal/todoplugin/ent/role" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/durationgql" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype" - "entgo.io/contrib/entgql/internal/todoplugin/ent/schema/uuidgql" "entgo.io/contrib/entgql/internal/todoplugin/ent/todo" + "entgo.io/contrib/entgql/internal/todouuid/ent/schema/uuidgql" "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" "github.com/google/uuid" @@ -51,7 +51,6 @@ type ResolverRoot interface { } type DirectiveRoot struct { - SomeDirective func(ctx context.Context, obj interface{}, next graphql.Resolver, stringArg *string, boolArg *bool) (res interface{}, err error) } type ComplexityRoot struct { @@ -587,12 +586,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er } var sources = []*ast.Source{ - {Name: "todo.graphql", Input: `directive @someDirective( - stringArg: String - boolArg: Boolean -) on OBJECT | INPUT_OBJECT | SCALAR | FIELD_DEFINITION - -type CategoryConfig { + {Name: "todo.graphql", Input: `type CategoryConfig { maxMembers: Int } @@ -825,30 +819,6 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** -func (ec *executionContext) dir_someDirective_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["stringArg"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("stringArg")) - arg0, err = ec.unmarshalOString2ᚖstring(ctx, tmp) - if err != nil { - return nil, err - } - } - args["stringArg"] = arg0 - var arg1 *bool - if tmp, ok := rawArgs["boolArg"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("boolArg")) - arg1, err = ec.unmarshalOBoolean2ᚖbool(ctx, tmp) - if err != nil { - return nil, err - } - } - args["boolArg"] = arg1 - 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{}{} @@ -1182,7 +1152,7 @@ func (ec *executionContext) _Category_config(ctx context.Context, field graphql. } res := resTmp.(*schematype.CategoryConfig) fc.Result = res - return ec.marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋschemaᚋschematypeᚐCategoryConfig(ctx, field.Selections, res) + return ec.marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodoᚋentᚋschemaᚋschematypeᚐCategoryConfig(ctx, field.Selections, res) } func (ec *executionContext) _Category_duration(ctx context.Context, field graphql.CollectedField, obj *ent.Category) (ret graphql.Marshaler) { @@ -5223,7 +5193,7 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se return res } -func (ec *executionContext) marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋschemaᚋschematypeᚐCategoryConfig(ctx context.Context, sel ast.SelectionSet, v *schematype.CategoryConfig) graphql.Marshaler { +func (ec *executionContext) marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodoᚋentᚋschemaᚋschematypeᚐCategoryConfig(ctx context.Context, sel ast.SelectionSet, v *schematype.CategoryConfig) graphql.Marshaler { if v == nil { if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { ec.Errorf(ctx, "must not be null") diff --git a/entgql/internal/todoplugin/gqlgen.yml b/entgql/internal/todoplugin/gqlgen.yml index 3f2dca500..13784a5bb 100644 --- a/entgql/internal/todoplugin/gqlgen.yml +++ b/entgql/internal/todoplugin/gqlgen.yml @@ -19,11 +19,11 @@ models: - github.com/99designs/gqlgen/graphql.Uint64 Duration: model: - - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/durationgql.Duration - UUID: - model: - - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/uuidgql.UUID + - entgo.io/contrib/entgql/internal/todo/ent/schema/durationgql.Duration # Custom mapping from GraphQL `CategoryConfigInput` to `schematype.CategoryConfig`. CategoryConfigInput: model: - - entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig + - entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig + UUID: + model: + - entgo.io/contrib/entgql/internal/todouuid/ent/schema/uuidgql.UUID diff --git a/entgql/internal/todoplugin/resolver.go b/entgql/internal/todoplugin/resolver.go index e8f49a854..1085d0942 100644 --- a/entgql/internal/todoplugin/resolver.go +++ b/entgql/internal/todoplugin/resolver.go @@ -15,8 +15,6 @@ package todoplugin import ( - "context" - "entgo.io/contrib/entgql/internal/todoplugin/ent" "github.com/99designs/gqlgen/graphql" ) @@ -27,11 +25,7 @@ type Resolver struct{ client *ent.Client } // NewSchema creates a graphql executable schema. func NewSchema(client *ent.Client) graphql.ExecutableSchema { return NewExecutableSchema(Config{ - Resolvers: &Resolver{client}, - Directives: DirectiveRoot{ - SomeDirective: func(ctx context.Context, obj interface{}, next graphql.Resolver, stringArg *string, boolArg *bool) (res interface{}, err error) { - return next(ctx) - }, - }, + Resolvers: &Resolver{client}, + Directives: DirectiveRoot{}, }) } diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql index d8120560b..f9be77feb 100644 --- a/entgql/internal/todoplugin/todo.graphql +++ b/entgql/internal/todoplugin/todo.graphql @@ -1,8 +1,3 @@ -directive @someDirective( - stringArg: String - boolArg: Boolean -) on OBJECT | INPUT_OBJECT | SCALAR | FIELD_DEFINITION - type CategoryConfig { maxMembers: Int } diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go index 106c83df1..0b82058a7 100644 --- a/entgql/plugin/plugin_config_test.go +++ b/entgql/plugin/plugin_config_test.go @@ -161,7 +161,7 @@ func TestModifyConfig_todoplugin(t *testing.T) { expected.Models = map[string]config.TypeMapEntry{ "Category": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Category"}}, "CategoryStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status"}}, - "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig"}}, + "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig"}}, "MasterUser": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.User"}}, "Role": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role"}}, "Status": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status"}}, @@ -183,7 +183,7 @@ func TestModifyConfig_todoplugin_relay(t *testing.T) { expected := config.DefaultConfig() expected.Models = map[string]config.TypeMapEntry{ "Category": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Category"}}, - "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/schema/schematype.CategoryConfig"}}, + "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig"}}, "CategoryConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryConnection"}}, "CategoryEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryEdge"}}, "CategoryOrder": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrder"}}, From f918251b07e1afddff3c54dbb8851c9b3bda5688 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 08:58:27 +0000 Subject: [PATCH 20/23] feat: generate enums from the field --- entgql/internal/todoplugin/generated.go | 50 ++++++++++++--------- entgql/internal/todoplugin/todo.graphql | 21 --------- entgql/plugin/plugin.go | 43 ++++++++++++++++++ entgql/plugin/plugin_test.go | 58 +++++++++++++++++++++++++ 4 files changed, 130 insertions(+), 42 deletions(-) diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go index aeb8546c5..e24832823 100644 --- a/entgql/internal/todoplugin/generated.go +++ b/entgql/internal/todoplugin/generated.go @@ -594,16 +594,6 @@ input CategoryConfigInput { maxMembers: Int } -enum CategoryStatus { - ENABLED - DISABLED -} - -enum Status { - IN_PROGRESS - COMPLETED -} - scalar Time scalar Duration scalar Uint64 @@ -640,17 +630,6 @@ input TodoOrder { field: TodoOrderField } -enum VisibilityStatus { - LISTING - HIDDEN -} - -enum Role { - ADMIN - USER - UNKNOWN -} - type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! @@ -705,6 +684,13 @@ type CategoryEdge { cursor: Cursor! } """ +CategoryStatus is enum for the field status +""" +enum CategoryStatus { + ENABLED + DISABLED +} +""" Define a Relay Cursor type: https://relay.dev/graphql/connections.htm#sec-Cursor """ @@ -776,6 +762,21 @@ type PageInfo { """ endCursor: Cursor } +""" +Role is enum for the field role +""" +enum Role { + ADMIN + USER + UNKNOWN +} +""" +Status is enum for the field status +""" +enum Status { + IN_PROGRESS + COMPLETED +} type Todo implements Node { id: ID! createdAt: Time! @@ -811,6 +812,13 @@ type TodoEdge { """ cursor: Cursor! } +""" +VisibilityStatus is enum for the field visibility_status +""" +enum VisibilityStatus { + LISTING + HIDDEN +} `, BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql index f9be77feb..1b7857479 100644 --- a/entgql/internal/todoplugin/todo.graphql +++ b/entgql/internal/todoplugin/todo.graphql @@ -6,16 +6,6 @@ input CategoryConfigInput { maxMembers: Int } -enum CategoryStatus { - ENABLED - DISABLED -} - -enum Status { - IN_PROGRESS - COMPLETED -} - scalar Time scalar Duration scalar Uint64 @@ -52,17 +42,6 @@ input TodoOrder { field: TodoOrderField } -enum VisibilityStatus { - LISTING - HIDDEN -} - -enum Role { - ADMIN - USER - UNKNOWN -} - type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index 8a1602230..af2a5d3b2 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -142,6 +142,16 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { Interfaces: interfaces, } + for _, field := range node.Fields { + enum, err := e.buildEnum(field) + if err != nil { + return nil, err + } + if enum != nil { + types[enum.Name] = enum + } + } + // TODO(giautm): Added RelayConnection annotation check if e.relaySpec { defs, err := relayConnectionTypes(node) @@ -156,6 +166,39 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { return types, nil } +func (e *EntGQL) buildEnum(f *gen.Field) (*ast.Definition, error) { + if !f.IsEnum() { + return nil, nil + } + + ant, err := entgql.DecodeAnnotation(f.Annotations) + if err != nil { + return nil, err + } + + // NOTE(giautm): I'm not sure this is + // the right approach, but it passed the test + defs, err := e.typeFromField(f, false, ant.Type) + if err != nil { + return nil, err + } + name := defs.Name() + + valueDefs := make(ast.EnumValueList, 0, len(f.Enums)) + for _, v := range f.Enums { + valueDefs = append(valueDefs, &ast.EnumValueDefinition{ + Name: v.Value, + }) + } + + return &ast.Definition{ + Name: name, + Kind: ast.Enum, + Description: fmt.Sprintf("%s is enum for the field %s", name, f.Name), + EnumValues: valueDefs, + }, nil +} + func (e *EntGQL) buildTypeFields(t *gen.Type) (ast.FieldList, error) { var fields ast.FieldList if t.ID != nil { diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go index 9a0c801cd..13a3d125d 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/plugin/plugin_test.go @@ -41,6 +41,13 @@ func TestEntGQL_buildTypes(t *testing.T) { duration: Duration! count: Uint64! } +""" +CategoryStatus is enum for the field status +""" +enum CategoryStatus { + ENABLED + DISABLED +} type MasterUser { id: ID username: String! @@ -49,6 +56,21 @@ type MasterUser { role: Role! nullableString: String } +""" +Role is enum for the field role +""" +enum Role { + ADMIN + USER + UNKNOWN +} +""" +Status is enum for the field status +""" +enum Status { + IN_PROGRESS + COMPLETED +} type Todo { id: ID! createdAt: Time! @@ -57,6 +79,13 @@ type Todo { priority: Int! text: String! } +""" +VisibilityStatus is enum for the field visibility_status +""" +enum VisibilityStatus { + LISTING + HIDDEN +} `, printSchema(&ast.Schema{ Types: types, })) @@ -107,6 +136,13 @@ type CategoryEdge { """ cursor: Cursor! } +""" +CategoryStatus is enum for the field status +""" +enum CategoryStatus { + ENABLED + DISABLED +} type MasterUser implements Node { id: ID! username: String! @@ -142,6 +178,21 @@ type MasterUserEdge { """ cursor: Cursor! } +""" +Role is enum for the field role +""" +enum Role { + ADMIN + USER + UNKNOWN +} +""" +Status is enum for the field status +""" +enum Status { + IN_PROGRESS + COMPLETED +} type Todo implements Node { id: ID! createdAt: Time! @@ -177,6 +228,13 @@ type TodoEdge { """ cursor: Cursor! } +""" +VisibilityStatus is enum for the field visibility_status +""" +enum VisibilityStatus { + LISTING + HIDDEN +} `, printSchema(&ast.Schema{ Types: types, })) From aa75875311fe84a55404f1cfc80b983a19c722ac Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Thu, 3 Mar 2022 12:29:20 +0000 Subject: [PATCH 21/23] feat: generate Order/OrderField objects --- entgql/internal/todoplugin/generated.go | 120 ++++++++++++++++++------ entgql/internal/todoplugin/todo.graphql | 12 --- entgql/plugin/plugin.go | 55 +++++++++-- entgql/plugin/plugin_test.go | 19 ++++ 4 files changed, 158 insertions(+), 48 deletions(-) diff --git a/entgql/internal/todoplugin/generated.go b/entgql/internal/todoplugin/generated.go index e24832823..3ead02479 100644 --- a/entgql/internal/todoplugin/generated.go +++ b/entgql/internal/todoplugin/generated.go @@ -618,18 +618,6 @@ enum OrderDirection { DESC } -enum TodoOrderField { - CREATED_AT - PRIORITY - STATUS - TEXT -} - -input TodoOrder { - direction: OrderDirection! - field: TodoOrderField -} - type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! @@ -683,6 +671,14 @@ type CategoryEdge { """ cursor: Cursor! } +input CategoryOrder { + direction: OrderDirection! = ASC + field: CategoryOrderField! +} +enum CategoryOrderField { + TEXT + DURATION +} """ CategoryStatus is enum for the field status """ @@ -812,6 +808,17 @@ type TodoEdge { """ cursor: Cursor! } +input TodoOrder { + direction: OrderDirection! = ASC + field: TodoOrderField! +} +enum TodoOrderField { + CREATED_AT + VISIBILITY_STATUS + STATUS + PRIORITY + TEXT +} """ VisibilityStatus is enum for the field visibility_status """ @@ -3839,6 +3846,41 @@ func (ec *executionContext) unmarshalInputCategoryConfigInput(ctx context.Contex return it, nil } +func (ec *executionContext) unmarshalInputCategoryOrder(ctx context.Context, obj interface{}) (ent.CategoryOrder, error) { + var it ent.CategoryOrder + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + if _, present := asMap["direction"]; !present { + asMap["direction"] = "ASC" + } + + for k, v := range asMap { + switch k { + case "direction": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("direction")) + it.Direction, err = ec.unmarshalNOrderDirection2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐOrderDirection(ctx, v) + if err != nil { + return it, err + } + case "field": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) + it.Field, err = ec.unmarshalNCategoryOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryOrderField(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputTodoInput(ctx context.Context, obj interface{}) (TodoInput, error) { var it TodoInput asMap := map[string]interface{}{} @@ -3905,6 +3947,10 @@ func (ec *executionContext) unmarshalInputTodoOrder(ctx context.Context, obj int asMap[k] = v } + if _, present := asMap["direction"]; !present { + asMap["direction"] = "ASC" + } + for k, v := range asMap { switch k { case "direction": @@ -3919,7 +3965,7 @@ func (ec *executionContext) unmarshalInputTodoOrder(ctx context.Context, obj int var err error ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("field")) - it.Field, err = ec.unmarshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx, v) + it.Field, err = ec.unmarshalNTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx, v) if err != nil { return it, err } @@ -5211,6 +5257,22 @@ func (ec *executionContext) marshalNCategoryConfig2ᚖentgoᚗioᚋcontribᚋent return ec._CategoryConfig(ctx, sel, v) } +func (ec *executionContext) unmarshalNCategoryOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryOrderField(ctx context.Context, v interface{}) (*ent.CategoryOrderField, error) { + var res = new(ent.CategoryOrderField) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCategoryOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐCategoryOrderField(ctx context.Context, sel ast.SelectionSet, v *ent.CategoryOrderField) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return v +} + func (ec *executionContext) unmarshalNCategoryStatus2entgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚋcategoryᚐStatus(ctx context.Context, v interface{}) (category.Status, error) { var res category.Status err := res.UnmarshalGQL(v) @@ -5444,6 +5506,22 @@ func (ec *executionContext) unmarshalNTodoInput2entgoᚗioᚋcontribᚋentgqlᚋ return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx context.Context, v interface{}) (*ent.TodoOrderField, error) { + var res = new(ent.TodoOrderField) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx context.Context, sel ast.SelectionSet, v *ent.TodoOrderField) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return v +} + func (ec *executionContext) unmarshalNUint642uint64(ctx context.Context, v interface{}) (uint64, error) { res, err := graphql.UnmarshalUint64(v) return res, graphql.ErrorOnPath(ctx, err) @@ -6066,22 +6144,6 @@ func (ec *executionContext) unmarshalOTodoOrder2ᚖentgoᚗioᚋcontribᚋentgql return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) unmarshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx context.Context, v interface{}) (*ent.TodoOrderField, error) { - if v == nil { - return nil, nil - } - var res = new(ent.TodoOrderField) - err := res.UnmarshalGQL(v) - return res, graphql.ErrorOnPath(ctx, err) -} - -func (ec *executionContext) marshalOTodoOrderField2ᚖentgoᚗioᚋcontribᚋentgqlᚋinternalᚋtodopluginᚋentᚐTodoOrderField(ctx context.Context, sel ast.SelectionSet, v *ent.TodoOrderField) graphql.Marshaler { - if v == nil { - return graphql.Null - } - return v -} - func (ec *executionContext) unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx context.Context, v interface{}) (*uuid.UUID, error) { if v == nil { return nil, nil diff --git a/entgql/internal/todoplugin/todo.graphql b/entgql/internal/todoplugin/todo.graphql index 1b7857479..a25a8d651 100644 --- a/entgql/internal/todoplugin/todo.graphql +++ b/entgql/internal/todoplugin/todo.graphql @@ -30,18 +30,6 @@ enum OrderDirection { DESC } -enum TodoOrderField { - CREATED_AT - PRIORITY - STATUS - TEXT -} - -input TodoOrder { - direction: OrderDirection! - field: TodoOrderField -} - type Query { node(id: ID!): Node nodes(ids: [ID!]!): [Node]! diff --git a/entgql/plugin/plugin.go b/entgql/plugin/plugin.go index af2a5d3b2..bb7fdcfe6 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/plugin/plugin.go @@ -142,8 +142,24 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { Interfaces: interfaces, } + var enumOrderByValues ast.EnumValueList for _, field := range node.Fields { - enum, err := e.buildEnum(field) + ant, err := entgql.DecodeAnnotation(field.Annotations) + if err != nil { + return nil, err + } + if ant.Skip { + continue + } + + // Check if this node has an OrderBy object + if ant.OrderField != "" { + enumOrderByValues = append(enumOrderByValues, &ast.EnumValueDefinition{ + Name: ant.OrderField, + }) + } + + enum, err := e.buildEnum(field, ant) if err != nil { return nil, err } @@ -160,22 +176,47 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { } insertDefinitions(types, defs...) + if enumOrderByValues != nil { + pagination, err := entgql.NodePaginationNames(node) + if err != nil { + return nil, err + } + + types[pagination.OrderField] = &ast.Definition{ + Name: pagination.OrderField, + Kind: ast.Enum, + EnumValues: enumOrderByValues, + } + types[pagination.Order] = &ast.Definition{ + Name: pagination.Order, + Kind: ast.InputObject, + Fields: ast.FieldList{ + { + Name: "direction", + Type: ast.NonNullNamedType("OrderDirection", nil), + DefaultValue: &ast.Value{ + Raw: "ASC", + Kind: ast.EnumValue, + }, + }, + { + Name: "field", + Type: ast.NonNullNamedType(pagination.OrderField, nil), + }, + }, + } + } } } return types, nil } -func (e *EntGQL) buildEnum(f *gen.Field) (*ast.Definition, error) { +func (e *EntGQL) buildEnum(f *gen.Field, ant *entgql.Annotation) (*ast.Definition, error) { if !f.IsEnum() { return nil, nil } - ant, err := entgql.DecodeAnnotation(f.Annotations) - if err != nil { - return nil, err - } - // NOTE(giautm): I'm not sure this is // the right approach, but it passed the test defs, err := e.typeFromField(f, false, ant.Type) diff --git a/entgql/plugin/plugin_test.go b/entgql/plugin/plugin_test.go index 13a3d125d..c566d38b0 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/plugin/plugin_test.go @@ -136,6 +136,14 @@ type CategoryEdge { """ cursor: Cursor! } +input CategoryOrder { + direction: OrderDirection! = ASC + field: CategoryOrderField! +} +enum CategoryOrderField { + TEXT + DURATION +} """ CategoryStatus is enum for the field status """ @@ -228,6 +236,17 @@ type TodoEdge { """ cursor: Cursor! } +input TodoOrder { + direction: OrderDirection! = ASC + field: TodoOrderField! +} +enum TodoOrderField { + CREATED_AT + VISIBILITY_STATUS + STATUS + PRIORITY + TEXT +} """ VisibilityStatus is enum for the field visibility_status """ From 22d0019f1f2e09d210169fe766cda416be39ef3a Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Fri, 4 Mar 2022 04:13:50 +0700 Subject: [PATCH 22/23] refactor: move generation logic to the extension See the comment: /~https://github.com/ent/ent/issues/2351#issuecomment-1058304867 --- entgql/extension.go | 38 ++++ entgql/internal/todoplugin/cmd/entgqlgen.go | 31 +-- entgql/plugin.go | 74 +++++++ entgql/plugin/plugin_config_test.go | 209 ------------------ entgql/{plugin/plugin.go => schema.go} | 90 ++------ .../plugin_config.go => schema_models.go} | 70 ++---- entgql/schema_models_test.go | 207 +++++++++++++++++ .../plugin_relay.go => schema_relay.go} | 5 +- ...gin_relay_test.go => schema_relay_test.go} | 2 +- .../{plugin/plugin_test.go => schema_test.go} | 13 +- 10 files changed, 385 insertions(+), 354 deletions(-) create mode 100644 entgql/plugin.go delete mode 100644 entgql/plugin/plugin_config_test.go rename entgql/{plugin/plugin.go => schema.go} (72%) rename entgql/{plugin/plugin_config.go => schema_models.go} (51%) create mode 100644 entgql/schema_models_test.go rename entgql/{plugin/plugin_relay.go => schema_relay.go} (97%) rename entgql/{plugin/plugin_relay_test.go => schema_relay_test.go} (99%) rename entgql/{plugin/plugin_test.go => schema_test.go} (93%) diff --git a/entgql/extension.go b/entgql/extension.go index 0f9630287..f03ede915 100644 --- a/entgql/extension.go +++ b/entgql/extension.go @@ -37,6 +37,8 @@ import ( "github.com/graphql-go/graphql/language/printer" "github.com/graphql-go/graphql/language/source" "github.com/graphql-go/graphql/language/visitor" + + ast2 "github.com/vektah/gqlparser/v2/ast" ) type ( @@ -49,6 +51,9 @@ type ( hooks []gen.Hook templates []*gen.Template scalarFunc func(*gen.Field, gen.Op) string + + schema *ast2.Schema + models map[string]string } // ExtensionOption allows for managing the Extension configuration @@ -188,6 +193,14 @@ func WithWhereFilters(b bool) ExtensionOption { } } +// WithSchemaGenerator add a hook for generate GQL schema +func WithSchemaGenerator() ExtensionOption { + return func(e *Extension) error { + e.hooks = append(e.hooks, e.genSchema()) + return nil + } +} + // WithMapScalarFunc allows users to provides a custom function that // maps an ent.Field (*gen.Field) into its GraphQL scalar type. If the // function returns an empty string, the extension fallbacks to the its @@ -313,6 +326,31 @@ func (e *Extension) isInput(name string) bool { return false } +// genSchema returns a new hook for generating +// the GraphQL schema from the graph. +func (e *Extension) genSchema() gen.Hook { + return func(next gen.Generator) gen.Generator { + return gen.GenerateFunc(func(g *gen.Graph) error { + if err := next.Generate(g); err != nil { + return err + } + + genSchema, err := newSchemaGenerator(g) + if err != nil { + return err + } + if e.schema, err = genSchema.prepareSchema(); err != nil { + return err + } + if e.models, err = genSchema.genModels(); err != nil { + return err + } + + return nil + }) + } +} + // genWhereInputs returns a new hook for generating // WhereInputs in the GraphQL schema. func (e *Extension) genWhereInputs() gen.Hook { diff --git a/entgql/internal/todoplugin/cmd/entgqlgen.go b/entgql/internal/todoplugin/cmd/entgqlgen.go index 71bebb18b..b66cb31de 100644 --- a/entgql/internal/todoplugin/cmd/entgqlgen.go +++ b/entgql/internal/todoplugin/cmd/entgqlgen.go @@ -19,7 +19,6 @@ import ( "log" "entgo.io/contrib/entgql" - "entgo.io/contrib/entgql/plugin" "entgo.io/ent/entc" "entgo.io/ent/entc/gen" "github.com/99designs/gqlgen/api" @@ -35,24 +34,9 @@ func main() { log.Fatal("entgqlgen: must specify schema path. use entgqlgen -path ./ent/schema") } - graph, err := entc.LoadGraph(*schemaPath, &gen.Config{}) - if err != nil { - log.Fatalf("entgqlgen: failed loading ent graph: %v", err) - } - - cfg, err := config.LoadConfigFromDefaultLocations() - if err != nil { - log.Fatalf("failed to load config %v", err) - } - - entgqlPlugin, err := plugin.NewEntGQLPlugin(graph, - plugin.WithRelaySpecification(true), + exEntGQL, err := entgql.NewExtension( + entgql.WithSchemaGenerator(), ) - if err != nil { - log.Fatalf("failed to create entgql plugin: %v", err) - } - - ex, err := entgql.NewExtension() if err != nil { log.Fatalf("creating entgql extension: %v", err) } @@ -74,12 +58,19 @@ func main() { // // Code generated by entc, DO NOT EDIT. `, - }, entc.Extensions(ex)) + }, entc.Extensions( + // EntGQL should be the latest extension in the list + exEntGQL, + )) if err != nil { log.Fatalf("running ent codegen: %v", err) } - err = api.Generate(cfg, api.PrependPlugin(entgqlPlugin)) + cfg, err := config.LoadConfigFromDefaultLocations() + if err != nil { + log.Fatalf("failed to load config %v", err) + } + err = api.Generate(cfg, api.PrependPlugin(exEntGQL.CreatePlugin())) if err != nil { log.Fatalf("running gqlgen: %v", err) } diff --git a/entgql/plugin.go b/entgql/plugin.go new file mode 100644 index 000000000..a4f13b6b9 --- /dev/null +++ b/entgql/plugin.go @@ -0,0 +1,74 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package entgql + +import ( + "strings" + + "github.com/99designs/gqlgen/codegen/config" + "github.com/99designs/gqlgen/plugin" + "github.com/vektah/gqlparser/v2/ast" + "github.com/vektah/gqlparser/v2/formatter" +) + +// CreatePlugin create the plugin for GQLGen +func (e *Extension) CreatePlugin() plugin.Plugin { + return &gqlgenPlugin{ + schema: e.schema, + models: e.models, + } +} + +type gqlgenPlugin struct { + schema *ast.Schema + models map[string]string +} + +var ( + _ plugin.Plugin = (*gqlgenPlugin)(nil) + _ plugin.EarlySourceInjector = (*gqlgenPlugin)(nil) + _ plugin.ConfigMutator = (*gqlgenPlugin)(nil) +) + +func (gqlgenPlugin) Name() string { + return "entgql" +} + +func (e *gqlgenPlugin) InjectSourceEarly() *ast.Source { + if e.schema == nil { + return nil + } + + sb := &strings.Builder{} + formatter.NewFormatter(sb).FormatSchema(e.schema) + + return &ast.Source{ + Name: "entgql.graphql", + Input: sb.String(), + BuiltIn: false, + } +} + +func (e *gqlgenPlugin) MutateConfig(cfg *config.Config) error { + if e.models != nil { + for name, goType := range e.models { + if !cfg.Models.Exists(name) { + cfg.Models.Add(name, goType) + } + } + } + + return nil +} diff --git a/entgql/plugin/plugin_config_test.go b/entgql/plugin/plugin_config_test.go deleted file mode 100644 index 0b82058a7..000000000 --- a/entgql/plugin/plugin_config_test.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2019-present Facebook -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package plugin - -import ( - "testing" - - "entgo.io/ent/entc" - "entgo.io/ent/entc/gen" - "entgo.io/ent/schema/field" - "github.com/99designs/gqlgen/codegen/config" - "github.com/stretchr/testify/require" -) - -func TestModifyConfig_empty(t *testing.T) { - e, err := NewEntGQLPlugin(&gen.Graph{ - Config: &gen.Config{ - Package: "example.com", - }, - }) - require.NoError(t, err) - cfg := config.DefaultConfig() - err = e.MutateConfig(cfg) - require.NoError(t, err) - expected := config.DefaultConfig() - expected.Models = map[string]config.TypeMapEntry{} - require.Equal(t, expected, cfg) -} - -var g = &gen.Graph{ - Config: &gen.Config{ - Package: "example.com", - IDType: &field.TypeInfo{ - Type: field.TypeInt, - }, - }, - Nodes: []*gen.Type{ - { - Name: "Todo", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - }, - { - Name: "User", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "Skip": true, - }, - }, - }, - { - Name: "Group", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "RelayConnection": true, - }, - }, - }, - { - Name: "GroupWithSort", - Fields: []*gen.Field{{ - Name: "Name", - Type: &field.TypeInfo{ - Type: field.TypeString, - }, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "OrderField": "NAME", - }, - }, - }}, - Annotations: map[string]interface{}{ - annotationName: map[string]interface{}{ - "RelayConnection": true, - }, - }, - }, - }, -} - -func TestModifyConfig(t *testing.T) { - e, err := NewEntGQLPlugin(g) - require.NoError(t, err) - cfg := config.DefaultConfig() - err = e.MutateConfig(cfg) - require.NoError(t, err) - expected := config.DefaultConfig() - expected.Models = map[string]config.TypeMapEntry{ - "Todo": {Model: []string{"example.com.Todo"}}, - "Group": {Model: []string{"example.com.Group"}}, - "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, - } - require.Equal(t, expected, cfg) -} - -func TestModifyConfig_relay(t *testing.T) { - e, err := NewEntGQLPlugin(g, WithRelaySpecification(true)) - require.NoError(t, err) - cfg := config.DefaultConfig() - err = e.MutateConfig(cfg) - require.NoError(t, err) - expected := config.DefaultConfig() - expected.Models = map[string]config.TypeMapEntry{ - "Cursor": {Model: []string{"example.com.Cursor"}}, - "Group": {Model: []string{"example.com.Group"}}, - "GroupConnection": {Model: []string{"example.com.GroupConnection"}}, - "GroupEdge": {Model: []string{"example.com.GroupEdge"}}, - "GroupWithSort": {Model: []string{"example.com.GroupWithSort"}}, - "GroupWithSortConnection": {Model: []string{"example.com.GroupWithSortConnection"}}, - "GroupWithSortEdge": {Model: []string{"example.com.GroupWithSortEdge"}}, - "GroupWithSortOrder": {Model: []string{"example.com.GroupWithSortOrder"}}, - "GroupWithSortOrderField": {Model: []string{"example.com.GroupWithSortOrderField"}}, - "Node": {Model: []string{"example.com.Noder"}}, - "OrderDirection": {Model: []string{"example.com.OrderDirection"}}, - "PageInfo": {Model: []string{"example.com.PageInfo"}}, - "Todo": {Model: []string{"example.com.Todo"}}, - "TodoConnection": {Model: []string{"example.com.TodoConnection"}}, - "TodoEdge": {Model: []string{"example.com.TodoEdge"}}, - } - require.Equal(t, expected, cfg) -} - -func TestModifyConfig_todoplugin(t *testing.T) { - graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) - require.NoError(t, err) - - e, err := NewEntGQLPlugin(graph) - require.NoError(t, err) - cfg := config.DefaultConfig() - err = e.MutateConfig(cfg) - require.NoError(t, err) - expected := config.DefaultConfig() - expected.Models = map[string]config.TypeMapEntry{ - "Category": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Category"}}, - "CategoryStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status"}}, - "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig"}}, - "MasterUser": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.User"}}, - "Role": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role"}}, - "Status": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status"}}, - "Todo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Todo"}}, - "VisibilityStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus"}}, - } - require.Equal(t, expected, cfg) -} - -func TestModifyConfig_todoplugin_relay(t *testing.T) { - graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) - require.NoError(t, err) - - e, err := NewEntGQLPlugin(graph, WithRelaySpecification(true)) - require.NoError(t, err) - cfg := config.DefaultConfig() - err = e.MutateConfig(cfg) - require.NoError(t, err) - expected := config.DefaultConfig() - expected.Models = map[string]config.TypeMapEntry{ - "Category": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Category"}}, - "CategoryConfig": {Model: []string{"entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig"}}, - "CategoryConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryConnection"}}, - "CategoryEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryEdge"}}, - "CategoryOrder": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrder"}}, - "CategoryOrderField": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrderField"}}, - "CategoryStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status"}}, - "Cursor": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Cursor"}}, - "MasterUser": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.User"}}, - "MasterUserConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserConnection"}}, - "MasterUserEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserEdge"}}, - "Node": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Noder"}}, - "OrderDirection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.OrderDirection"}}, - "PageInfo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.PageInfo"}}, - "Role": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role"}}, - "Status": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status"}}, - "Todo": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.Todo"}}, - "TodoConnection": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoConnection"}}, - "TodoEdge": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoEdge"}}, - "TodoOrder": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoOrder"}}, - "TodoOrderField": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent.TodoOrderField"}}, - "VisibilityStatus": {Model: []string{"entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus"}}, - } - require.Equal(t, expected, cfg) -} diff --git a/entgql/plugin/plugin.go b/entgql/schema.go similarity index 72% rename from entgql/plugin/plugin.go rename to entgql/schema.go index bb7fdcfe6..6e4988583 100644 --- a/entgql/plugin/plugin.go +++ b/entgql/schema.go @@ -12,90 +12,43 @@ // See the License for the specific language governing permissions and // limitations under the License. -package plugin +package entgql import ( "fmt" "strings" - "entgo.io/contrib/entgql" "entgo.io/ent/entc/gen" "entgo.io/ent/schema/field" - "github.com/99designs/gqlgen/plugin" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/formatter" ) type ( - // EntGQL is a plugin that generates GQL schema from the Ent's Graph - EntGQL struct { + // TODO(giautm): refactor internal APIs + schemaGenerator struct { graph *gen.Graph nodes []*gen.Type - schema *ast.Schema relaySpec bool } - - // EntGQLOption is a option for the EntGQL plugin - EntGQLOption func(*EntGQL) error -) - -var ( - annotationName = entgql.Annotation{}.Name() - camel = gen.Funcs["camel"].(func(string) string) - - _ plugin.Plugin = (*EntGQL)(nil) - _ plugin.EarlySourceInjector = (*EntGQL)(nil) - _ plugin.ConfigMutator = (*EntGQL)(nil) ) -// WithRelaySpecification adds the Relay specification to the schema -func WithRelaySpecification(relaySpec bool) EntGQLOption { - return func(e *EntGQL) error { - e.relaySpec = relaySpec - return nil - } -} - -// NewEntGQLPlugin creates a new EntGQL plugin -func NewEntGQLPlugin(graph *gen.Graph, opts ...EntGQLOption) (*EntGQL, error) { - nodes, err := entgql.FilterNodes(graph.Nodes) +func newSchemaGenerator(g *gen.Graph) (*schemaGenerator, error) { + nodes, err := FilterNodes(g.Nodes) if err != nil { return nil, err } - e := &EntGQL{ - graph: graph, + return &schemaGenerator{ + graph: g, nodes: nodes, - } - for _, opt := range opts { - if err = opt(e); err != nil { - return nil, err - } - } - - e.schema, err = e.prepareSchema() - if err != nil { - return nil, fmt.Errorf("entgql: failed to prepare the GQL schema: %w", err) - } - - return e, nil -} - -// Name implements the Plugin interface. -func (*EntGQL) Name() string { - return "entgql" -} - -// InjectSourceEarly implements the EarlySourceInjector interface. -func (e *EntGQL) InjectSourceEarly() *ast.Source { - return &ast.Source{ - Name: "entgql.graphql", - Input: printSchema(e.schema), - BuiltIn: false, - } + // TODO(giautm): relaySpec enable by default. + // Add an option to disable it. + relaySpec: true, + }, nil } -func (e *EntGQL) prepareSchema() (*ast.Schema, error) { +func (e *schemaGenerator) prepareSchema() (*ast.Schema, error) { types, err := e.buildTypes() if err != nil { return nil, err @@ -109,10 +62,11 @@ func (e *EntGQL) prepareSchema() (*ast.Schema, error) { }, nil } -func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { +func (e *schemaGenerator) buildTypes() (map[string]*ast.Definition, error) { types := map[string]*ast.Definition{} + for _, node := range e.nodes { - ant, err := entgql.DecodeAnnotation(node.Annotations) + ant, err := DecodeAnnotation(node.Annotations) if err != nil { return nil, err } @@ -144,7 +98,7 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { var enumOrderByValues ast.EnumValueList for _, field := range node.Fields { - ant, err := entgql.DecodeAnnotation(field.Annotations) + ant, err := DecodeAnnotation(field.Annotations) if err != nil { return nil, err } @@ -177,7 +131,7 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { insertDefinitions(types, defs...) if enumOrderByValues != nil { - pagination, err := entgql.NodePaginationNames(node) + pagination, err := NodePaginationNames(node) if err != nil { return nil, err } @@ -212,7 +166,7 @@ func (e *EntGQL) buildTypes() (map[string]*ast.Definition, error) { return types, nil } -func (e *EntGQL) buildEnum(f *gen.Field, ant *entgql.Annotation) (*ast.Definition, error) { +func (e *schemaGenerator) buildEnum(f *gen.Field, ant *Annotation) (*ast.Definition, error) { if !f.IsEnum() { return nil, nil } @@ -240,7 +194,7 @@ func (e *EntGQL) buildEnum(f *gen.Field, ant *entgql.Annotation) (*ast.Definitio }, nil } -func (e *EntGQL) buildTypeFields(t *gen.Type) (ast.FieldList, error) { +func (e *schemaGenerator) buildTypeFields(t *gen.Type) (ast.FieldList, error) { var fields ast.FieldList if t.ID != nil { f, err := e.typeField(t.ID, true) @@ -264,8 +218,8 @@ func (e *EntGQL) buildTypeFields(t *gen.Type) (ast.FieldList, error) { return fields, nil } -func (e *EntGQL) typeField(f *gen.Field, isID bool) ([]*ast.FieldDefinition, error) { - ant, err := entgql.DecodeAnnotation(f.Annotations) +func (e *schemaGenerator) typeField(f *gen.Field, isID bool) ([]*ast.FieldDefinition, error) { + ant, err := DecodeAnnotation(f.Annotations) if err != nil { return nil, err } @@ -295,7 +249,7 @@ func namedType(name string, nullable bool) *ast.Type { return ast.NonNullNamedType(name, nil) } -func (e *EntGQL) typeFromField(f *gen.Field, idField bool, userDefinedType string) (*ast.Type, error) { +func (e *schemaGenerator) typeFromField(f *gen.Field, idField bool, userDefinedType string) (*ast.Type, error) { nillable := f.Nillable typ := f.Type.Type diff --git a/entgql/plugin/plugin_config.go b/entgql/schema_models.go similarity index 51% rename from entgql/plugin/plugin_config.go rename to entgql/schema_models.go index cc0107484..3183ef928 100644 --- a/entgql/plugin/plugin_config.go +++ b/entgql/schema_models.go @@ -12,34 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -package plugin +package entgql import ( "fmt" - - "entgo.io/contrib/entgql" - "github.com/99designs/gqlgen/codegen/config" ) -// MutateConfig implements the ConfigMutator interface -func (e *EntGQL) MutateConfig(cfg *config.Config) error { +func (e *schemaGenerator) genModels() (map[string]string, error) { + models := map[string]string{} + if e.relaySpec { - if !cfg.Models.Exists(RelayPageInfo) { - cfg.Models.Add(RelayPageInfo, e.entGoType(RelayPageInfo)) - } - if !cfg.Models.Exists(RelayNode) { - // Bind to Noder interface - cfg.Models.Add(RelayNode, e.entGoType("Noder")) - } - if !cfg.Models.Exists(RelayCursor) { - cfg.Models.Add(RelayCursor, e.entGoType(RelayCursor)) - } + models[RelayPageInfo] = e.entGoType(RelayPageInfo) + models[RelayNode] = e.entGoType("Noder") + models[RelayCursor] = e.entGoType(RelayCursor) } - for _, node := range e.nodes { - ant, err := entgql.DecodeAnnotation(node.Annotations) + ant, err := DecodeAnnotation(node.Annotations) if err != nil { - return err + return nil, err } if ant.Skip { continue @@ -49,15 +39,13 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { if ant.Type != "" { name = ant.Type } - if !cfg.Models.Exists(name) { - cfg.Models.Add(name, e.entGoType(node.Name)) - } + models[name] = e.entGoType(node.Name) hasOrderBy := false for _, field := range node.Fields { - ant, err := entgql.DecodeAnnotation(field.Annotations) + ant, err := DecodeAnnotation(field.Annotations) if err != nil { - return err + return nil, err } if ant.Skip { continue @@ -82,46 +70,34 @@ func (e *EntGQL) MutateConfig(cfg *config.Config) error { // the right approach, but it passed the test defs, err := e.typeFromField(field, false, ant.Type) if err != nil { - return err + return nil, err } name := defs.Name() - if !cfg.Models.Exists(name) { - cfg.Models.Add(name, goType) - } + models[name] = goType } // TODO(giautm): Added RelayConnection annotation check if e.relaySpec { - pagination, err := entgql.NodePaginationNames(node) + pagination, err := NodePaginationNames(node) if err != nil { - return err + return nil, err } - if !cfg.Models.Exists(pagination.Connection) { - cfg.Models.Add(pagination.Connection, e.entGoType(pagination.Connection)) - } - if !cfg.Models.Exists(pagination.Edge) { - cfg.Models.Add(pagination.Edge, e.entGoType(pagination.Edge)) - } + models[pagination.Connection] = e.entGoType(pagination.Connection) + models[pagination.Edge] = e.entGoType(pagination.Edge) if hasOrderBy { - if !cfg.Models.Exists("OrderDirection") { - cfg.Models.Add("OrderDirection", e.entGoType("OrderDirection")) - } - cfg.Models[pagination.Order] = config.TypeMapEntry{ - Model: []string{e.entGoType(pagination.Order)}, - } - cfg.Models[pagination.OrderField] = config.TypeMapEntry{ - Model: []string{e.entGoType(pagination.OrderField)}, - } + models["OrderDirection"] = e.entGoType("OrderDirection") + models[pagination.Order] = e.entGoType(pagination.Order) + models[pagination.OrderField] = e.entGoType(pagination.OrderField) } } } - return nil + return models, nil } -func (e *EntGQL) entGoType(name string) string { +func (e *schemaGenerator) entGoType(name string) string { return fmt.Sprintf("%s.%s", e.graph.Package, name) } diff --git a/entgql/schema_models_test.go b/entgql/schema_models_test.go new file mode 100644 index 000000000..b98d67a01 --- /dev/null +++ b/entgql/schema_models_test.go @@ -0,0 +1,207 @@ +// Copyright 2019-present Facebook +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package entgql + +import ( + "testing" + + "entgo.io/ent/entc" + "entgo.io/ent/entc/gen" + "entgo.io/ent/schema/field" + "github.com/stretchr/testify/require" +) + +func TestModifyConfig_empty(t *testing.T) { + e, err := newSchemaGenerator(&gen.Graph{ + Config: &gen.Config{ + Package: "example.com", + }, + }) + require.NoError(t, err) + e.relaySpec = false + + cfg, err := e.genModels() + require.NoError(t, err) + + expected := map[string]string{} + require.Equal(t, expected, cfg) +} + +var g = &gen.Graph{ + Config: &gen.Config{ + Package: "example.com", + IDType: &field.TypeInfo{ + Type: field.TypeInt, + }, + }, + Nodes: []*gen.Type{ + { + Name: "Todo", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + }, + { + Name: "User", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "Skip": true, + }, + }, + }, + { + Name: "Group", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, + }, + }, + { + Name: "GroupWithSort", + Fields: []*gen.Field{{ + Name: "Name", + Type: &field.TypeInfo{ + Type: field.TypeString, + }, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "OrderField": "NAME", + }, + }, + }}, + Annotations: map[string]interface{}{ + annotationName: map[string]interface{}{ + "RelayConnection": true, + }, + }, + }, + }, +} + +func TestModifyConfig(t *testing.T) { + e, err := newSchemaGenerator(g) + require.NoError(t, err) + + e.relaySpec = false + cfg, err := e.genModels() + require.NoError(t, err) + expected := map[string]string{ + "Todo": "example.com.Todo", + "Group": "example.com.Group", + "GroupWithSort": "example.com.GroupWithSort", + } + require.Equal(t, expected, cfg) +} + +func TestModifyConfig_relay(t *testing.T) { + e, err := newSchemaGenerator(g) + require.NoError(t, err) + + cfg, err := e.genModels() + require.NoError(t, err) + expected := map[string]string{ + "Cursor": "example.com.Cursor", + "Group": "example.com.Group", + "GroupConnection": "example.com.GroupConnection", + "GroupEdge": "example.com.GroupEdge", + "GroupWithSort": "example.com.GroupWithSort", + "GroupWithSortConnection": "example.com.GroupWithSortConnection", + "GroupWithSortEdge": "example.com.GroupWithSortEdge", + "GroupWithSortOrder": "example.com.GroupWithSortOrder", + "GroupWithSortOrderField": "example.com.GroupWithSortOrderField", + "Node": "example.com.Noder", + "OrderDirection": "example.com.OrderDirection", + "PageInfo": "example.com.PageInfo", + "Todo": "example.com.Todo", + "TodoConnection": "example.com.TodoConnection", + "TodoEdge": "example.com.TodoEdge", + } + require.Equal(t, expected, cfg) +} + +func TestModifyConfig_todoplugin(t *testing.T) { + graph, err := entc.LoadGraph("./internal/todoplugin/ent/schema", &gen.Config{}) + require.NoError(t, err) + + e, err := newSchemaGenerator(graph) + require.NoError(t, err) + e.relaySpec = false + + cfg, err := e.genModels() + require.NoError(t, err) + + expected := map[string]string{ + "Category": "entgo.io/contrib/entgql/internal/todoplugin/ent.Category", + "CategoryStatus": "entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status", + "CategoryConfig": "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig", + "MasterUser": "entgo.io/contrib/entgql/internal/todoplugin/ent.User", + "Role": "entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role", + "Status": "entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status", + "Todo": "entgo.io/contrib/entgql/internal/todoplugin/ent.Todo", + "VisibilityStatus": "entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus", + } + require.Equal(t, expected, cfg) +} + +func TestModifyConfig_todoplugin_relay(t *testing.T) { + graph, err := entc.LoadGraph("./internal/todoplugin/ent/schema", &gen.Config{}) + require.NoError(t, err) + + e, err := newSchemaGenerator(graph) + require.NoError(t, err) + cfg, err := e.genModels() + require.NoError(t, err) + expected := map[string]string{ + "Category": "entgo.io/contrib/entgql/internal/todoplugin/ent.Category", + "CategoryConfig": "entgo.io/contrib/entgql/internal/todo/ent/schema/schematype.CategoryConfig", + "CategoryConnection": "entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryConnection", + "CategoryEdge": "entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryEdge", + "CategoryOrder": "entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrder", + "CategoryOrderField": "entgo.io/contrib/entgql/internal/todoplugin/ent.CategoryOrderField", + "CategoryStatus": "entgo.io/contrib/entgql/internal/todoplugin/ent/category.Status", + "Cursor": "entgo.io/contrib/entgql/internal/todoplugin/ent.Cursor", + "MasterUser": "entgo.io/contrib/entgql/internal/todoplugin/ent.User", + "MasterUserConnection": "entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserConnection", + "MasterUserEdge": "entgo.io/contrib/entgql/internal/todoplugin/ent.MasterUserEdge", + "Node": "entgo.io/contrib/entgql/internal/todoplugin/ent.Noder", + "OrderDirection": "entgo.io/contrib/entgql/internal/todoplugin/ent.OrderDirection", + "PageInfo": "entgo.io/contrib/entgql/internal/todoplugin/ent.PageInfo", + "Role": "entgo.io/contrib/entgql/internal/todoplugin/ent/role.Role", + "Status": "entgo.io/contrib/entgql/internal/todoplugin/ent/todo.Status", + "Todo": "entgo.io/contrib/entgql/internal/todoplugin/ent.Todo", + "TodoConnection": "entgo.io/contrib/entgql/internal/todoplugin/ent.TodoConnection", + "TodoEdge": "entgo.io/contrib/entgql/internal/todoplugin/ent.TodoEdge", + "TodoOrder": "entgo.io/contrib/entgql/internal/todoplugin/ent.TodoOrder", + "TodoOrderField": "entgo.io/contrib/entgql/internal/todoplugin/ent.TodoOrderField", + "VisibilityStatus": "entgo.io/contrib/entgql/internal/todoplugin/ent/todo.VisibilityStatus", + } + require.Equal(t, expected, cfg) +} diff --git a/entgql/plugin/plugin_relay.go b/entgql/schema_relay.go similarity index 97% rename from entgql/plugin/plugin_relay.go rename to entgql/schema_relay.go index fb160a9ad..b423ad4ae 100644 --- a/entgql/plugin/plugin_relay.go +++ b/entgql/schema_relay.go @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package plugin +package entgql import ( - "entgo.io/contrib/entgql" "entgo.io/ent/entc/gen" "github.com/vektah/gqlparser/v2/ast" ) @@ -82,7 +81,7 @@ https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo`, } func relayConnectionTypes(t *gen.Type) ([]*ast.Definition, error) { - pagination, err := entgql.NodePaginationNames(t) + pagination, err := NodePaginationNames(t) if err != nil { return nil, err } diff --git a/entgql/plugin/plugin_relay_test.go b/entgql/schema_relay_test.go similarity index 99% rename from entgql/plugin/plugin_relay_test.go rename to entgql/schema_relay_test.go index 26bde868a..c7e668633 100644 --- a/entgql/plugin/plugin_relay_test.go +++ b/entgql/schema_relay_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package plugin +package entgql import ( "reflect" diff --git a/entgql/plugin/plugin_test.go b/entgql/schema_test.go similarity index 93% rename from entgql/plugin/plugin_test.go rename to entgql/schema_test.go index c566d38b0..5e8ca1fc7 100644 --- a/entgql/plugin/plugin_test.go +++ b/entgql/schema_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package plugin +package entgql import ( "testing" @@ -24,11 +24,12 @@ import ( ) func TestEntGQL_buildTypes(t *testing.T) { - graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) + graph, err := entc.LoadGraph("./internal/todoplugin/ent/schema", &gen.Config{}) require.NoError(t, err) - plugin, err := NewEntGQLPlugin(graph) - + plugin, err := newSchemaGenerator(graph) require.NoError(t, err) + plugin.relaySpec = false + types, err := plugin.buildTypes() require.NoError(t, err) @@ -92,9 +93,9 @@ enum VisibilityStatus { } func TestEntGQL_buildTypes_todoplugin_relay(t *testing.T) { - graph, err := entc.LoadGraph("../internal/todoplugin/ent/schema", &gen.Config{}) + graph, err := entc.LoadGraph("./internal/todoplugin/ent/schema", &gen.Config{}) require.NoError(t, err) - plugin, err := NewEntGQLPlugin(graph, WithRelaySpecification(true)) + plugin, err := newSchemaGenerator(graph) require.NoError(t, err) types, err := plugin.buildTypes() From fbe0297c710d772f568e87745c339d0a134f41a2 Mon Sep 17 00:00:00 2001 From: "Giau. Tran Minh" Date: Fri, 4 Mar 2022 04:18:56 +0700 Subject: [PATCH 23/23] fix: reduce public APIs --- entgql/annotation.go | 4 ++-- entgql/extension.go | 6 +++--- entgql/schema.go | 10 +++++----- entgql/schema_models.go | 6 +++--- entgql/schema_relay.go | 2 +- entgql/template.go | 32 ++++++++++++++++---------------- entgql/template_test.go | 6 +++--- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/entgql/annotation.go b/entgql/annotation.go index f785099e3..b2f78bfaa 100644 --- a/entgql/annotation.go +++ b/entgql/annotation.go @@ -126,8 +126,8 @@ func (a *Annotation) Decode(annotation interface{}) error { return json.Unmarshal(buf, a) } -// DecodeAnnotation decodes the annotation from the schema. -func DecodeAnnotation(annotations gen.Annotations) (*Annotation, error) { +// decodeAnnotation decodes the annotation from the schema. +func decodeAnnotation(annotations gen.Annotations) (*Annotation, error) { ant := &Annotation{} if annotations == nil || annotations[ant.Name()] == nil { return ant, nil diff --git a/entgql/extension.go b/entgql/extension.go index f03ede915..a72b8b08a 100644 --- a/entgql/extension.go +++ b/entgql/extension.go @@ -360,7 +360,7 @@ func (e *Extension) genWhereInputs() gen.Hook { } inputs := make(map[string]*ast.InputObjectDefinition) return gen.GenerateFunc(func(g *gen.Graph) error { - nodes, err := FilterNodes(g.Nodes) + nodes, err := filterNodes(g.Nodes) if err != nil { return err } @@ -454,7 +454,7 @@ func (e *Extension) whereType(t *gen.Type) (string, *ast.InputObjectDefinition, }), })) } - fields, err := FilterFields(append(t.Fields, t.ID)) + fields, err := filterFields(append(t.Fields, t.ID)) if err != nil { return "", nil, err } @@ -472,7 +472,7 @@ func (e *Extension) whereType(t *gen.Type) (string, *ast.InputObjectDefinition, input.Fields = append(input.Fields, fd) } } - edges, err := FilterEdges(t.Edges) + edges, err := filterEdges(t.Edges) if err != nil { return "", nil, err } diff --git a/entgql/schema.go b/entgql/schema.go index 6e4988583..05307c07a 100644 --- a/entgql/schema.go +++ b/entgql/schema.go @@ -34,7 +34,7 @@ type ( ) func newSchemaGenerator(g *gen.Graph) (*schemaGenerator, error) { - nodes, err := FilterNodes(g.Nodes) + nodes, err := filterNodes(g.Nodes) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func (e *schemaGenerator) buildTypes() (map[string]*ast.Definition, error) { types := map[string]*ast.Definition{} for _, node := range e.nodes { - ant, err := DecodeAnnotation(node.Annotations) + ant, err := decodeAnnotation(node.Annotations) if err != nil { return nil, err } @@ -98,7 +98,7 @@ func (e *schemaGenerator) buildTypes() (map[string]*ast.Definition, error) { var enumOrderByValues ast.EnumValueList for _, field := range node.Fields { - ant, err := DecodeAnnotation(field.Annotations) + ant, err := decodeAnnotation(field.Annotations) if err != nil { return nil, err } @@ -131,7 +131,7 @@ func (e *schemaGenerator) buildTypes() (map[string]*ast.Definition, error) { insertDefinitions(types, defs...) if enumOrderByValues != nil { - pagination, err := NodePaginationNames(node) + pagination, err := nodePaginationNames(node) if err != nil { return nil, err } @@ -219,7 +219,7 @@ func (e *schemaGenerator) buildTypeFields(t *gen.Type) (ast.FieldList, error) { } func (e *schemaGenerator) typeField(f *gen.Field, isID bool) ([]*ast.FieldDefinition, error) { - ant, err := DecodeAnnotation(f.Annotations) + ant, err := decodeAnnotation(f.Annotations) if err != nil { return nil, err } diff --git a/entgql/schema_models.go b/entgql/schema_models.go index 3183ef928..5b3c93312 100644 --- a/entgql/schema_models.go +++ b/entgql/schema_models.go @@ -27,7 +27,7 @@ func (e *schemaGenerator) genModels() (map[string]string, error) { models[RelayCursor] = e.entGoType(RelayCursor) } for _, node := range e.nodes { - ant, err := DecodeAnnotation(node.Annotations) + ant, err := decodeAnnotation(node.Annotations) if err != nil { return nil, err } @@ -43,7 +43,7 @@ func (e *schemaGenerator) genModels() (map[string]string, error) { hasOrderBy := false for _, field := range node.Fields { - ant, err := DecodeAnnotation(field.Annotations) + ant, err := decodeAnnotation(field.Annotations) if err != nil { return nil, err } @@ -79,7 +79,7 @@ func (e *schemaGenerator) genModels() (map[string]string, error) { // TODO(giautm): Added RelayConnection annotation check if e.relaySpec { - pagination, err := NodePaginationNames(node) + pagination, err := nodePaginationNames(node) if err != nil { return nil, err } diff --git a/entgql/schema_relay.go b/entgql/schema_relay.go index b423ad4ae..e953ea3ce 100644 --- a/entgql/schema_relay.go +++ b/entgql/schema_relay.go @@ -81,7 +81,7 @@ https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo`, } func relayConnectionTypes(t *gen.Type) ([]*ast.Definition, error) { - pagination, err := NodePaginationNames(t) + pagination, err := nodePaginationNames(t) if err != nil { return nil, err } diff --git a/entgql/template.go b/entgql/template.go index 4e7a6fc31..8ed65f57b 100644 --- a/entgql/template.go +++ b/entgql/template.go @@ -66,11 +66,11 @@ var ( // TemplateFuncs contains the extra template functions used by entgql. TemplateFuncs = template.FuncMap{ "fieldCollections": fieldCollections, - "filterEdges": FilterEdges, - "filterFields": FilterFields, - "filterNodes": FilterNodes, - "findIDType": FindIDType, - "nodePaginationNames": NodePaginationNames, + "filterEdges": filterEdges, + "filterFields": filterFields, + "filterNodes": filterNodes, + "findIDType": findIDType, + "nodePaginationNames": nodePaginationNames, } //go:embed template/* @@ -83,8 +83,8 @@ func parseT(path string) *gen.Template { ParseFS(templates, path)) } -// FindIDType returns the type of the ID field of the given type. -func FindIDType(nodes []*gen.Type, defaultType *field.TypeInfo) (*field.TypeInfo, error) { +// findIDType returns the type of the ID field of the given type. +func findIDType(nodes []*gen.Type, defaultType *field.TypeInfo) (*field.TypeInfo, error) { t := defaultType if len(nodes) > 0 { t = nodes[0].ID.Type @@ -135,8 +135,8 @@ func fieldCollections(edges []*gen.Edge) (map[string]fieldCollection, error) { return result, nil } -// FilterNodes filters out nodes that should not be included in the GraphQL schema. -func FilterNodes(nodes []*gen.Type) ([]*gen.Type, error) { +// filterNodes filters out nodes that should not be included in the GraphQL schema. +func filterNodes(nodes []*gen.Type) ([]*gen.Type, error) { var filteredNodes []*gen.Type for _, n := range nodes { ant := &Annotation{} @@ -153,8 +153,8 @@ func FilterNodes(nodes []*gen.Type) ([]*gen.Type, error) { return filteredNodes, nil } -// FilterEdges filters out edges that should not be included in the GraphQL schema. -func FilterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { +// filterEdges filters out edges that should not be included in the GraphQL schema. +func filterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { var filteredEdges []*gen.Edge for _, e := range edges { ant := &Annotation{} @@ -180,8 +180,8 @@ func FilterEdges(edges []*gen.Edge) ([]*gen.Edge, error) { return filteredEdges, nil } -// FilterFields filters out fields that should not be included in the GraphQL schema. -func FilterFields(fields []*gen.Field) ([]*gen.Field, error) { +// filterFields filters out fields that should not be included in the GraphQL schema. +func filterFields(fields []*gen.Field) ([]*gen.Field, error) { var filteredFields []*gen.Field for _, f := range fields { ant := &Annotation{} @@ -207,10 +207,10 @@ type PaginationNames struct { OrderField string } -// NodePaginationNames returns the names of the pagination types for the node. -func NodePaginationNames(t *gen.Type) (*PaginationNames, error) { +// nodePaginationNames returns the names of the pagination types for the node. +func nodePaginationNames(t *gen.Type) (*PaginationNames, error) { node := t.Name - ant, err := DecodeAnnotation(t.Annotations) + ant, err := decodeAnnotation(t.Annotations) if err != nil { return nil, err } diff --git a/entgql/template_test.go b/entgql/template_test.go index 6aa8a5a89..234efb390 100644 --- a/entgql/template_test.go +++ b/entgql/template_test.go @@ -24,7 +24,7 @@ import ( var annotationName = Annotation{}.Name() func TestFilterNodes(t *testing.T) { - nodes, err := FilterNodes([]*gen.Type{ + nodes, err := filterNodes([]*gen.Type{ { Name: "Type1", Annotations: map[string]interface{}{ @@ -58,7 +58,7 @@ func TestFilterNodes(t *testing.T) { } func TestFilterEdges(t *testing.T) { - edges, err := FilterEdges([]*gen.Edge{ + edges, err := filterEdges([]*gen.Edge{ { Name: "Edge1", Type: &gen.Type{}, @@ -178,7 +178,7 @@ func TestFieldCollections(t *testing.T) { } func TestFilterFields(t *testing.T) { - fields, err := FilterFields([]*gen.Field{ + fields, err := filterFields([]*gen.Field{ { Name: "Field1", Annotations: map[string]interface{}{