graphql: Actually get the bugs from the repo

Quentin Gliech created

Change summary

bug/comment.go     |  4 ++--
bug/person.go      |  4 ++--
bug/snapshot.go    |  8 ++++----
commands/webui.go  |  2 +-
graphql/handler.go | 35 +++++++++++++++++++++++++++--------
graphql/schema.go  | 38 ++++++++++++++++++++++++++------------
graphql/types.go   | 38 ++++++++++++++++++++++++++++++++++++--
7 files changed, 98 insertions(+), 31 deletions(-)

Detailed changes

bug/comment.go 🔗

@@ -6,8 +6,8 @@ import (
 )
 
 type Comment struct {
-	Author  Person
-	Message string
+	Author  Person `json:"author"`
+	Message string `json:"message"`
 
 	// Creation time of the comment.
 	// Should be used only for human display, never for ordering as we can't rely on it in a distributed system.

bug/person.go 🔗

@@ -6,8 +6,8 @@ import (
 )
 
 type Person struct {
-	Name  string
-	Email string
+	Name  string `json:"name"`
+	Email string `json:"email"`
 }
 
 // GetUser will query the repository for user detail and build the corresponding Person

bug/snapshot.go 🔗

@@ -10,10 +10,10 @@ import (
 type Snapshot struct {
 	id string
 
-	Status   Status
-	Title    string
-	Comments []Comment
-	Labels   []Label
+	Status   Status    `json:"status"`
+	Title    string    `json:"title"`
+	Comments []Comment `json:"comments"`
+	Labels   []Label   `json:"labels"`
 
 	Operations []Operation
 }

commands/webui.go 🔗

@@ -23,7 +23,7 @@ func runWebUI(cmd *cobra.Command, args []string) error {
 
 	fmt.Printf("Web UI available at %s\n", webUiAddr)
 
-	graphqlHandler, err := graphql.NewHandler()
+	graphqlHandler, err := graphql.NewHandler(repo)
 
 	if err != nil {
 		return err

graphql/handler.go 🔗

@@ -1,17 +1,36 @@
 package graphql
 
-import "github.com/graphql-go/handler"
+import (
+	"context"
+	"net/http"
 
-func NewHandler() (*handler.Handler, error) {
-	schema, err := newGraphqlSchema()
+	"github.com/MichaelMure/git-bug/repository"
+	"github.com/graphql-go/handler"
+)
+
+type Handler struct {
+	Handler *handler.Handler
+	Repo    repository.Repo
+}
+
+func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	ctx := context.WithValue(r.Context(), "repo", h.Repo)
+	h.Handler.ContextHandler(ctx, w, r)
+}
+
+func NewHandler(repo repository.Repo) (*Handler, error) {
+	schema, err := graphqlSchema()
 
 	if err != nil {
 		return nil, err
 	}
 
-	return handler.New(&handler.Config{
-		Schema:   &schema,
-		Pretty:   true,
-		GraphiQL: true,
-	}), nil
+	return &Handler{
+		Handler: handler.New(&handler.Config{
+			Schema:   &schema,
+			Pretty:   true,
+			GraphiQL: true,
+		}),
+		Repo: repo,
+	}, nil
 }

graphql/schema.go 🔗

@@ -1,21 +1,35 @@
 package graphql
 
-import "github.com/graphql-go/graphql"
+import (
+	"github.com/MichaelMure/git-bug/bug"
+	"github.com/MichaelMure/git-bug/repository"
+	"github.com/graphql-go/graphql"
+)
 
-func newGraphqlSchema() (graphql.Schema, error) {
+func graphqlSchema() (graphql.Schema, error) {
+	fields := graphql.Fields{
+		"bug": &graphql.Field{
+			Type: bugType,
+			Args: graphql.FieldConfigArgument{
+				"id": &graphql.ArgumentConfig{
+					Type: bugIdScalar,
+				},
+			},
+			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
+				repo := p.Context.Value("repo").(repository.Repo)
+				id, _ := p.Args["id"].(string)
+				bug, err := bug.FindBug(repo, id)
+				if err != nil {
+					return nil, err
+				}
+
+				snapshot := bug.Compile()
 
-	rootQuery := graphql.ObjectConfig{
-		Name: "RootQuery",
-		Fields: graphql.Fields{
-			"hello": &graphql.Field{
-				Type: graphql.String,
+				return snapshot, nil
 			},
 		},
 	}
-
-	schemaConfig := graphql.SchemaConfig{
-		Query: graphql.NewObject(rootQuery),
-	}
-
+	rootQuery := graphql.ObjectConfig{Name: "RootQuery", Fields: fields}
+	schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(rootQuery)}
 	return graphql.NewSchema(schemaConfig)
 }

graphql/types.go 🔗

@@ -1,13 +1,44 @@
 package graphql
 
-import "github.com/graphql-go/graphql"
+import (
+	"fmt"
+
+	"github.com/graphql-go/graphql"
+	"github.com/graphql-go/graphql/language/ast"
+
+	"github.com/MichaelMure/git-bug/bug"
+)
+
+func coerceString(value interface{}) interface{} {
+	if v, ok := value.(*string); ok {
+		return *v
+	}
+	return fmt.Sprintf("%v", value)
+}
+
+var bugIdScalar = graphql.NewScalar(graphql.ScalarConfig{
+	Name:        "BugID",
+	Description: "TODO",
+	Serialize:   coerceString,
+	ParseValue:  coerceString,
+	ParseLiteral: func(valueAST ast.Value) interface{} {
+		switch valueAST := valueAST.(type) {
+		case *ast.StringValue:
+			return valueAST.Value
+		}
+		return nil
+	},
+})
 
 // Internally, it's the Snapshot
 var bugType = graphql.NewObject(graphql.ObjectConfig{
 	Name: "Bug",
 	Fields: graphql.Fields{
 		"id": &graphql.Field{
-			Type: graphql.String,
+			Type: bugIdScalar,
+			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
+				return p.Source.(bug.Snapshot).Id(), nil
+			},
 		},
 		"status": &graphql.Field{
 			Type: graphql.String,
@@ -17,6 +48,9 @@ var bugType = graphql.NewObject(graphql.ObjectConfig{
 		},
 		"labels": &graphql.Field{
 			Type: graphql.NewList(graphql.String),
+			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
+				return p.Source.(bug.Snapshot).Labels, nil
+			},
 		},
 		// TODO: operations
 	},