$ go run -mod=mod entgo.io/ent/cmd/ent new Todo
schema の設定。
// Fields of the Todo.
func (Todo) Fields() []ent.Field {
return []ent.Field{
field.String("title"),
field.String("note"),
field.Bool("completed").Default(false),
field.Time("created_at").Default(time.Now()),
field.Time("updated_at").Default(time.Now()),
}
}
$ go generate ./ent
$ printf '// +build tools\npackage tools\nimport (_ "github.com/99designs/gqlgen"\n _ "github.com/99designs/gqlgen/graphql/introspection")' | gofmt > tools.go
$ go mod tidy
$ go run github.com/99designs/gqlgen init
graph/
に生成されたファイル。
tree graph/
graph/
├── generated.go # 自動生成
├── model
│ └── models_gen.go # 自動生成
├── resolver.go
├── schema.graphqls
└── schema.resolvers.go
ファイルは resolver.go
、schema.graphqls
、schema.resolvers.go
で良さそう。
プロジェクト直下に生成された gqlgen.yml
は一旦放置。
schema.graphqls / schema.resolvers.go
を削除し、新規にスキーマ定義ファイルを作る。
共有インターフェイス Node を定義する。プライマリーキーを持つ場合は Node インターフェイスを作るのがお作法らしい。また、独自の型として Datetime を定義する。
interface Node {
id: ID!
}
scalar Datetime
次に Todo スキーマを定義する。
type Todo implements Node {
id: ID!
title: String!
note: String!
completed: Boolean!
created_at: Datetime!
updated_at: Datetime!
}
最後に query と mutation を定義する。
type Query {
todos: [Todo!]!
}
type Mutation {
createTodo(input: NewTodo!): Todo!
}
input NewTodo {
id: ID
title: String!
note: String!
completed: Boolean
created_at: Datetime
updated_at: Datetime
}
$ go run github.com/99designs/gqlgen
resolver から参照できるようにフィールドを追加する。
type Resolver struct {
EntClient *ent.Client
}
query.resolvers.go
を実装する。
// Todos is the resolver for the todos field.
func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) {
todos := []*model.Todo{}
searched, _ := r.EntClient.Todo.Query().All(ctx)
for _, todo := range searched {
todos = append(todos, &model.Todo{
ID: strconv.Itoa(todo.ID),
Title: todo.Title,
Note: todo.Note,
Completed: todo.Completed,
CreatedAt: todo.CreatedAt.String(),
UpdatedAt: todo.UpdatedAt.String(),
})
}
return todos, nil
}
mutation.resolvers.go
を実装する。
// CreateTodo is the resolver for the createTodo field.
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
created, _ := r.EntClient.Todo.Create().
SetTitle(input.Title).
SetNote(input.Note).
Save(ctx)
return &model.Todo{
ID: strconv.Itoa(created.ID),
Title: created.Title,
Note: created.Note,
Completed: created.Completed,
CreatedAt: created.CreatedAt.String(),
UpdatedAt: created.UpdatedAt.String(),
}, nil
}
最後は echo で実行できるようにする。server.go
は不要なので削除。
package main
import (
"context"
"gqlgen-todo/ent"
"gqlgen-todo/graph"
"net/http"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/labstack/echo/v4"
_ "github.com/mattn/go-sqlite3"
)
const (
DRIVER = "sqlite3"
DATA_SOURCE = "file:ent?mode=memory&cache=shared&_fk=1"
)
func main() {
ctx := context.Background()
client, _ := ent.Open(DRIVER, DATA_SOURCE)
client.Schema.Create(ctx)
e := echo.New()
e.GET("/health", func(c echo.Context) error {
return c.String(http.StatusOK, "ok")
})
graphqlHandler := handler.NewDefaultServer(
graph.NewExecutableSchema(
graph.Config{
Resolvers: &graph.Resolver{
EntClient: client,
},
},
),
)
playgroudHandler := playground.Handler("GraphQL", "/query")
e.POST("/query", func(c echo.Context) error {
graphqlHandler.ServeHTTP(c.Response(), c.Request())
return nil
})
e.GET("playground", func(c echo.Context) error {
playgroudHandler.ServeHTTP(c.Response(), c.Request())
return nil
})
e.Logger.Fatal(e.Start(":8080"))
}
mutation {
createTodo(input: {
title: "title1",
note: "note1"
}) {
id
title
note
completed
created_at
updated_at
}
}
{
"data": {
"createTodo": {
"id": "1",
"title": "title1",
"note": "note1",
"completed": false,
"created_at": "2023-02-23 17:33:13",
"updated_at": "2023-02-23 17:33:13"
}
}
}
{
todos {
id
title
note
completed
created_at
updated_at
}
}
{
"data": {
"todos": [
{
"id": "1",
"title": "title1",
"note": "note1",
"completed": false,
"created_at": "2023-02-23 17:33:13",
"updated_at": "2023-02-23 17:33:13"
},
{
"id": "2",
"title": "title2",
"note": "note2",
"completed": false,
"created_at": "2023-02-23 17:33:13",
"updated_at": "2023-02-23 17:33:13"
},
{
"id": "3",
"title": "title3",
"note": "note3",
"completed": false,
"created_at": "2023-02-23 17:33:13",
"updated_at": "2023-02-23 17:33:13"
}
]
}
}