aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gopkg.lock6
-rw-r--r--graphql/connections/connection_template.go13
-rw-r--r--graphql/connections/connections.go9
-rw-r--r--graphql/connections/gen_bug.go10
-rw-r--r--graphql/connections/gen_comment.go10
-rw-r--r--graphql/connections/gen_identity.go110
-rw-r--r--graphql/connections/gen_operation.go10
-rw-r--r--graphql/connections/gen_timeline.go10
-rw-r--r--graphql/connections/lazy_identity.go12
-rw-r--r--graphql/graph/gen_graph.go757
-rw-r--r--graphql/models/edges.go5
-rw-r--r--graphql/models/gen_models.go13
-rw-r--r--graphql/resolvers/bug.go9
-rw-r--r--graphql/resolvers/identity.go7
-rw-r--r--graphql/resolvers/mutation.go3
-rw-r--r--graphql/resolvers/query.go3
-rw-r--r--graphql/resolvers/repo.go81
-rw-r--r--graphql/resolvers/root.go2
-rw-r--r--graphql/schema/bug.graphql17
-rw-r--r--graphql/schema/identity.graphql14
-rw-r--r--graphql/schema/repository.graphql35
-rw-r--r--graphql/schema/root.graphql22
-rw-r--r--graphql/schema/types.graphql21
-rw-r--r--vendor/github.com/99designs/gqlgen/graphql/version.go2
-rw-r--r--vendor/github.com/99designs/gqlgen/handler/graphql.go28
-rw-r--r--vendor/github.com/99designs/gqlgen/handler/websocket.go42
26 files changed, 1121 insertions, 130 deletions
diff --git a/Gopkg.lock b/Gopkg.lock
index eb03979c..40e69d5b 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -2,7 +2,7 @@
[[projects]]
- digest = "1:cc0bbbf01f9f639555f9a9d4d5ff9c72da4c4c4bfe71f02fd318d37498270d80"
+ digest = "1:e8f6639eaa399c8595b9a2dee175514a9f3842888dc080e2776360dc604150dc"
name = "github.com/99designs/gqlgen"
packages = [
"cmd",
@@ -16,8 +16,8 @@
"internal/imports",
]
pruneopts = "UT"
- revision = "3a7f37c7e22a8fedce430c4d340ad5c1351198f4"
- version = "v0.7.1"
+ revision = "da1e07f5876c0fb79cbad19006f7135be08590d6"
+ version = "v0.7.2"
[[projects]]
branch = "master"
diff --git a/graphql/connections/connection_template.go b/graphql/connections/connection_template.go
index e20375b8..e98f53eb 100644
--- a/graphql/connections/connection_template.go
+++ b/graphql/connections/connection_template.go
@@ -7,6 +7,9 @@ import (
"github.com/cheekybits/genny/generic"
)
+// Name define the name of the connection
+type Name generic.Type
+
// NodeType define the node type handled by this relay connection
type NodeType generic.Type
@@ -18,17 +21,17 @@ type ConnectionType generic.Type
// NodeTypeEdgeMaker define a function that take a NodeType and an offset and
// create an Edge.
-type NodeTypeEdgeMaker func(value NodeType, offset int) Edge
+type NameEdgeMaker func(value NodeType, offset int) Edge
-// NodeTypeConMaker define a function that create a ConnectionType
-type NodeTypeConMaker func(
+// NameConMaker define a function that create a ConnectionType
+type NameConMaker func(
edges []EdgeType,
nodes []NodeType,
info models.PageInfo,
totalCount int) (ConnectionType, error)
-// NodeTypeCon will paginate a source according to the input of a relay connection
-func NodeTypeCon(source []NodeType, edgeMaker NodeTypeEdgeMaker, conMaker NodeTypeConMaker, input models.ConnectionInput) (ConnectionType, error) {
+// NameCon will paginate a source according to the input of a relay connection
+func NameCon(source []NodeType, edgeMaker NameEdgeMaker, conMaker NameConMaker, input models.ConnectionInput) (ConnectionType, error) {
var nodes []NodeType
var edges []EdgeType
var cursors []string
diff --git a/graphql/connections/connections.go b/graphql/connections/connections.go
index 68608116..cdc6d07f 100644
--- a/graphql/connections/connections.go
+++ b/graphql/connections/connections.go
@@ -1,7 +1,8 @@
-//go:generate genny -in=connection_template.go -out=gen_bug.go gen "NodeType=string EdgeType=LazyBugEdge ConnectionType=models.BugConnection"
-//go:generate genny -in=connection_template.go -out=gen_operation.go gen "NodeType=bug.Operation EdgeType=models.OperationEdge ConnectionType=models.OperationConnection"
-//go:generate genny -in=connection_template.go -out=gen_comment.go gen "NodeType=bug.Comment EdgeType=models.CommentEdge ConnectionType=models.CommentConnection"
-//go:generate genny -in=connection_template.go -out=gen_timeline.go gen "NodeType=bug.TimelineItem EdgeType=models.TimelineItemEdge ConnectionType=models.TimelineItemConnection"
+//go:generate genny -in=connection_template.go -out=gen_bug.go gen "Name=LazyBug NodeType=string EdgeType=LazyBugEdge ConnectionType=models.BugConnection"
+//go:generate genny -in=connection_template.go -out=gen_identity.go gen "Name=LazyIdentity NodeType=string EdgeType=LazyIdentityEdge ConnectionType=models.IdentityConnection"
+//go:generate genny -in=connection_template.go -out=gen_operation.go gen "Name=Operation NodeType=bug.Operation EdgeType=models.OperationEdge ConnectionType=models.OperationConnection"
+//go:generate genny -in=connection_template.go -out=gen_comment.go gen "Name=Comment NodeType=bug.Comment EdgeType=models.CommentEdge ConnectionType=models.CommentConnection"
+//go:generate genny -in=connection_template.go -out=gen_timeline.go gen "Name=TimelineItem NodeType=bug.TimelineItem EdgeType=models.TimelineItemEdge ConnectionType=models.TimelineItemConnection"
// Package connections implement a generic GraphQL relay connection
package connections
diff --git a/graphql/connections/gen_bug.go b/graphql/connections/gen_bug.go
index 000ff109..ba0a65fa 100644
--- a/graphql/connections/gen_bug.go
+++ b/graphql/connections/gen_bug.go
@@ -12,17 +12,17 @@ import (
// StringEdgeMaker define a function that take a string and an offset and
// create an Edge.
-type StringEdgeMaker func(value string, offset int) Edge
+type LazyBugEdgeMaker func(value string, offset int) Edge
-// StringConMaker define a function that create a models.BugConnection
-type StringConMaker func(
+// LazyBugConMaker define a function that create a models.BugConnection
+type LazyBugConMaker func(
edges []LazyBugEdge,
nodes []string,
info models.PageInfo,
totalCount int) (models.BugConnection, error)
-// StringCon will paginate a source according to the input of a relay connection
-func StringCon(source []string, edgeMaker StringEdgeMaker, conMaker StringConMaker, input models.ConnectionInput) (models.BugConnection, error) {
+// LazyBugCon will paginate a source according to the input of a relay connection
+func LazyBugCon(source []string, edgeMaker LazyBugEdgeMaker, conMaker LazyBugConMaker, input models.ConnectionInput) (models.BugConnection, error) {
var nodes []string
var edges []LazyBugEdge
var cursors []string
diff --git a/graphql/connections/gen_comment.go b/graphql/connections/gen_comment.go
index 5c8b0eea..6df21c58 100644
--- a/graphql/connections/gen_comment.go
+++ b/graphql/connections/gen_comment.go
@@ -13,17 +13,17 @@ import (
// BugCommentEdgeMaker define a function that take a bug.Comment and an offset and
// create an Edge.
-type BugCommentEdgeMaker func(value bug.Comment, offset int) Edge
+type CommentEdgeMaker func(value bug.Comment, offset int) Edge
-// BugCommentConMaker define a function that create a models.CommentConnection
-type BugCommentConMaker func(
+// CommentConMaker define a function that create a models.CommentConnection
+type CommentConMaker func(
edges []models.CommentEdge,
nodes []bug.Comment,
info models.PageInfo,
totalCount int) (models.CommentConnection, error)
-// BugCommentCon will paginate a source according to the input of a relay connection
-func BugCommentCon(source []bug.Comment, edgeMaker BugCommentEdgeMaker, conMaker BugCommentConMaker, input models.ConnectionInput) (models.CommentConnection, error) {
+// CommentCon will paginate a source according to the input of a relay connection
+func CommentCon(source []bug.Comment, edgeMaker CommentEdgeMaker, conMaker CommentConMaker, input models.ConnectionInput) (models.CommentConnection, error) {
var nodes []bug.Comment
var edges []models.CommentEdge
var cursors []string
diff --git a/graphql/connections/gen_identity.go b/graphql/connections/gen_identity.go
new file mode 100644
index 00000000..28501171
--- /dev/null
+++ b/graphql/connections/gen_identity.go
@@ -0,0 +1,110 @@
+// This file was automatically generated by genny.
+// Any changes will be lost if this file is regenerated.
+// see https://github.com/cheekybits/genny
+
+package connections
+
+import (
+ "fmt"
+
+ "github.com/MichaelMure/git-bug/graphql/models"
+)
+
+// StringEdgeMaker define a function that take a string and an offset and
+// create an Edge.
+type LazyIdentityEdgeMaker func(value string, offset int) Edge
+
+// LazyIdentityConMaker define a function that create a models.IdentityConnection
+type LazyIdentityConMaker func(
+ edges []LazyIdentityEdge,
+ nodes []string,
+ info models.PageInfo,
+ totalCount int) (models.IdentityConnection, error)
+
+// LazyIdentityCon will paginate a source according to the input of a relay connection
+func LazyIdentityCon(source []string, edgeMaker LazyIdentityEdgeMaker, conMaker LazyIdentityConMaker, input models.ConnectionInput) (models.IdentityConnection, error) {
+ var nodes []string
+ var edges []LazyIdentityEdge
+ var cursors []string
+ var pageInfo models.PageInfo
+ var totalCount = len(source)
+
+ emptyCon, _ := conMaker(edges, nodes, pageInfo, 0)
+
+ offset := 0
+
+ if input.After != nil {
+ for i, value := range source {
+ edge := edgeMaker(value, i)
+ if edge.GetCursor() == *input.After {
+ // remove all previous element including the "after" one
+ source = source[i+1:]
+ offset = i + 1
+ pageInfo.HasPreviousPage = true
+ break
+ }
+ }
+ }
+
+ if input.Before != nil {
+ for i, value := range source {
+ edge := edgeMaker(value, i+offset)
+
+ if edge.GetCursor() == *input.Before {
+ // remove all after element including the "before" one
+ pageInfo.HasNextPage = true
+ break
+ }
+
+ edges = append(edges, edge.(LazyIdentityEdge))
+ cursors = append(cursors, edge.GetCursor())
+ nodes = append(nodes, value)
+ }
+ } else {
+ edges = make([]LazyIdentityEdge, len(source))
+ cursors = make([]string, len(source))
+ nodes = source
+
+ for i, value := range source {
+ edge := edgeMaker(value, i+offset)
+ edges[i] = edge.(LazyIdentityEdge)
+ cursors[i] = edge.GetCursor()
+ }
+ }
+
+ if input.First != nil {
+ if *input.First < 0 {
+ return emptyCon, fmt.Errorf("first less than zero")
+ }
+
+ if len(edges) > *input.First {
+ // Slice result to be of length first by removing edges from the end
+ edges = edges[:*input.First]
+ cursors = cursors[:*input.First]
+ nodes = nodes[:*input.First]
+ pageInfo.HasNextPage = true
+ }
+ }
+
+ if input.Last != nil {
+ if *input.Last < 0 {
+ return emptyCon, fmt.Errorf("last less than zero")
+ }
+
+ if len(edges) > *input.Last {
+ // Slice result to be of length last by removing edges from the start
+ edges = edges[len(edges)-*input.Last:]
+ cursors = cursors[len(cursors)-*input.Last:]
+ nodes = nodes[len(nodes)-*input.Last:]
+ pageInfo.HasPreviousPage = true
+ }
+ }
+
+ // Fill up pageInfo cursors
+ if len(cursors) > 0 {
+ pageInfo.StartCursor = cursors[0]
+ pageInfo.EndCursor = cursors[len(cursors)-1]
+ }
+
+ return conMaker(edges, nodes, pageInfo, totalCount)
+}
diff --git a/graphql/connections/gen_operation.go b/graphql/connections/gen_operation.go
index 9a1a53b7..3fbd724f 100644
--- a/graphql/connections/gen_operation.go
+++ b/graphql/connections/gen_operation.go
@@ -13,17 +13,17 @@ import (
// BugOperationEdgeMaker define a function that take a bug.Operation and an offset and
// create an Edge.
-type BugOperationEdgeMaker func(value bug.Operation, offset int) Edge
+type OperationEdgeMaker func(value bug.Operation, offset int) Edge
-// BugOperationConMaker define a function that create a models.OperationConnection
-type BugOperationConMaker func(
+// OperationConMaker define a function that create a models.OperationConnection
+type OperationConMaker func(
edges []models.OperationEdge,
nodes []bug.Operation,
info models.PageInfo,
totalCount int) (models.OperationConnection, error)
-// BugOperationCon will paginate a source according to the input of a relay connection
-func BugOperationCon(source []bug.Operation, edgeMaker BugOperationEdgeMaker, conMaker BugOperationConMaker, input models.ConnectionInput) (models.OperationConnection, error) {
+// OperationCon will paginate a source according to the input of a relay connection
+func OperationCon(source []bug.Operation, edgeMaker OperationEdgeMaker, conMaker OperationConMaker, input models.ConnectionInput) (models.OperationConnection, error) {
var nodes []bug.Operation
var edges []models.OperationEdge
var cursors []string
diff --git a/graphql/connections/gen_timeline.go b/graphql/connections/gen_timeline.go
index 4d417a45..1a4b2fe5 100644
--- a/graphql/connections/gen_timeline.go
+++ b/graphql/connections/gen_timeline.go
@@ -13,17 +13,17 @@ import (
// BugTimelineItemEdgeMaker define a function that take a bug.TimelineItem and an offset and
// create an Edge.
-type BugTimelineItemEdgeMaker func(value bug.TimelineItem, offset int) Edge
+type TimelineItemEdgeMaker func(value bug.TimelineItem, offset int) Edge
-// BugTimelineItemConMaker define a function that create a models.TimelineItemConnection
-type BugTimelineItemConMaker func(
+// TimelineItemConMaker define a function that create a models.TimelineItemConnection
+type TimelineItemConMaker func(
edges []models.TimelineItemEdge,
nodes []bug.TimelineItem,
info models.PageInfo,
totalCount int) (models.TimelineItemConnection, error)
-// BugTimelineItemCon will paginate a source according to the input of a relay connection
-func BugTimelineItemCon(source []bug.TimelineItem, edgeMaker BugTimelineItemEdgeMaker, conMaker BugTimelineItemConMaker, input models.ConnectionInput) (models.TimelineItemConnection, error) {
+// TimelineItemCon will paginate a source according to the input of a relay connection
+func TimelineItemCon(source []bug.TimelineItem, edgeMaker TimelineItemEdgeMaker, conMaker TimelineItemConMaker, input models.ConnectionInput) (models.TimelineItemConnection, error) {
var nodes []bug.TimelineItem
var edges []models.TimelineItemEdge
var cursors []string
diff --git a/graphql/connections/lazy_identity.go b/graphql/connections/lazy_identity.go
new file mode 100644
index 00000000..34ba579a
--- /dev/null
+++ b/graphql/connections/lazy_identity.go
@@ -0,0 +1,12 @@
+package connections
+
+// LazyIdentityEdge is a special relay edge used to implement a lazy loading connection
+type LazyIdentityEdge struct {
+ Id string
+ Cursor string
+}
+
+// GetCursor return the cursor of a LazyIdentityEdge
+func (lbe LazyIdentityEdge) GetCursor() string {
+ return lbe.Cursor
+}
diff --git a/graphql/graph/gen_graph.go b/graphql/graph/gen_graph.go
index 548e808a..06ebecc7 100644
--- a/graphql/graph/gen_graph.go
+++ b/graphql/graph/gen_graph.go
@@ -161,6 +161,7 @@ type ComplexityRoot struct {
Identity struct {
Id func(childComplexity int) int
+ HumanId func(childComplexity int) int
Name func(childComplexity int) int
Email func(childComplexity int) int
Login func(childComplexity int) int
@@ -169,6 +170,18 @@ type ComplexityRoot struct {
IsProtected func(childComplexity int) int
}
+ IdentityConnection struct {
+ Edges func(childComplexity int) int
+ Nodes func(childComplexity int) int
+ PageInfo func(childComplexity int) int
+ TotalCount func(childComplexity int) int
+ }
+
+ IdentityEdge struct {
+ Cursor func(childComplexity int) int
+ Node func(childComplexity int) int
+ }
+
LabelChangeOperation struct {
Hash func(childComplexity int) int
Author func(childComplexity int) int
@@ -220,8 +233,11 @@ type ComplexityRoot struct {
}
Repository struct {
- AllBugs func(childComplexity int, after *string, before *string, first *int, last *int, query *string) int
- Bug func(childComplexity int, prefix string) int
+ AllBugs func(childComplexity int, after *string, before *string, first *int, last *int, query *string) int
+ Bug func(childComplexity int, prefix string) int
+ AllIdentities func(childComplexity int, after *string, before *string, first *int, last *int) int
+ Identity func(childComplexity int, prefix string) int
+ UserIdentity func(childComplexity int) int
}
SetStatusOperation struct {
@@ -297,6 +313,7 @@ type EditCommentOperationResolver interface {
}
type IdentityResolver interface {
ID(ctx context.Context, obj *identity.Interface) (string, error)
+ HumanID(ctx context.Context, obj *identity.Interface) (string, error)
Name(ctx context.Context, obj *identity.Interface) (*string, error)
Email(ctx context.Context, obj *identity.Interface) (*string, error)
Login(ctx context.Context, obj *identity.Interface) (*string, error)
@@ -326,6 +343,9 @@ type QueryResolver interface {
type RepositoryResolver interface {
AllBugs(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, query *string) (models.BugConnection, error)
Bug(ctx context.Context, obj *models.Repository, prefix string) (*bug.Snapshot, error)
+ AllIdentities(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (models.IdentityConnection, error)
+ Identity(ctx context.Context, obj *models.Repository, prefix string) (*identity.Interface, error)
+ UserIdentity(ctx context.Context, obj *models.Repository) (*identity.Interface, error)
}
type SetStatusOperationResolver interface {
Date(ctx context.Context, obj *bug.SetStatusOperation) (time.Time, error)
@@ -959,6 +979,83 @@ func field_Repository_bug_args(rawArgs map[string]interface{}) (map[string]inter
}
+func field_Repository_allIdentities_args(rawArgs map[string]interface{}) (map[string]interface{}, error) {
+ args := map[string]interface{}{}
+ var arg0 *string
+ if tmp, ok := rawArgs["after"]; ok {
+ var err error
+ var ptr1 string
+ if tmp != nil {
+ ptr1, err = graphql.UnmarshalString(tmp)
+ arg0 = &ptr1
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["after"] = arg0
+ var arg1 *string
+ if tmp, ok := rawArgs["before"]; ok {
+ var err error
+ var ptr1 string
+ if tmp != nil {
+ ptr1, err = graphql.UnmarshalString(tmp)
+ arg1 = &ptr1
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["before"] = arg1
+ var arg2 *int
+ if tmp, ok := rawArgs["first"]; ok {
+ var err error
+ var ptr1 int
+ if tmp != nil {
+ ptr1, err = graphql.UnmarshalInt(tmp)
+ arg2 = &ptr1
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["first"] = arg2
+ var arg3 *int
+ if tmp, ok := rawArgs["last"]; ok {
+ var err error
+ var ptr1 int
+ if tmp != nil {
+ ptr1, err = graphql.UnmarshalInt(tmp)
+ arg3 = &ptr1
+ }
+
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["last"] = arg3
+ return args, nil
+
+}
+
+func field_Repository_identity_args(rawArgs map[string]interface{}) (map[string]interface{}, error) {
+ args := map[string]interface{}{}
+ var arg0 string
+ if tmp, ok := rawArgs["prefix"]; ok {
+ var err error
+ arg0, err = graphql.UnmarshalString(tmp)
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["prefix"] = arg0
+ return args, nil
+
+}
+
func field___Type_fields_args(rawArgs map[string]interface{}) (map[string]interface{}, error) {
args := map[string]interface{}{}
var arg0 bool
@@ -1465,6 +1562,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Identity.Id(childComplexity), true
+ case "Identity.humanId":
+ if e.complexity.Identity.HumanId == nil {
+ break
+ }
+
+ return e.complexity.Identity.HumanId(childComplexity), true
+
case "Identity.name":
if e.complexity.Identity.Name == nil {
break
@@ -1507,6 +1611,48 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Identity.IsProtected(childComplexity), true
+ case "IdentityConnection.edges":
+ if e.complexity.IdentityConnection.Edges == nil {
+ break
+ }
+
+ return e.complexity.IdentityConnection.Edges(childComplexity), true
+
+ case "IdentityConnection.nodes":
+ if e.complexity.IdentityConnection.Nodes == nil {
+ break
+ }
+
+ return e.complexity.IdentityConnection.Nodes(childComplexity), true
+
+ case "IdentityConnection.pageInfo":
+ if e.complexity.IdentityConnection.PageInfo == nil {
+ break
+ }
+
+ return e.complexity.IdentityConnection.PageInfo(childComplexity), true
+
+ case "IdentityConnection.totalCount":
+ if e.complexity.IdentityConnection.TotalCount == nil {
+ break
+ }
+
+ return e.complexity.IdentityConnection.TotalCount(childComplexity), true
+
+ case "IdentityEdge.cursor":
+ if e.complexity.IdentityEdge.Cursor == nil {
+ break
+ }
+
+ return e.complexity.IdentityEdge.Cursor(childComplexity), true
+
+ case "IdentityEdge.node":
+ if e.complexity.IdentityEdge.Node == nil {
+ break
+ }
+
+ return e.complexity.IdentityEdge.Node(childComplexity), true
+
case "LabelChangeOperation.hash":
if e.complexity.LabelChangeOperation.Hash == nil {
break
@@ -1774,6 +1920,37 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Repository.Bug(childComplexity, args["prefix"].(string)), true
+ case "Repository.allIdentities":
+ if e.complexity.Repository.AllIdentities == nil {
+ break
+ }
+
+ args, err := field_Repository_allIdentities_args(rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.AllIdentities(childComplexity, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int)), true
+
+ case "Repository.identity":
+ if e.complexity.Repository.Identity == nil {
+ break
+ }
+
+ args, err := field_Repository_identity_args(rawArgs)
+ if err != nil {
+ return 0, false
+ }
+
+ return e.complexity.Repository.Identity(childComplexity, args["prefix"].(string)), true
+
+ case "Repository.userIdentity":
+ if e.complexity.Repository.UserIdentity == nil {
+ break
+ }
+
+ return e.complexity.Repository.UserIdentity(childComplexity), true
+
case "SetStatusOperation.hash":
if e.complexity.SetStatusOperation.Hash == nil {
break
@@ -4680,6 +4857,15 @@ func (ec *executionContext) _Identity(ctx context.Context, sel ast.SelectionSet,
}
wg.Done()
}(i, field)
+ case "humanId":
+ wg.Add(1)
+ go func(i int, field graphql.CollectedField) {
+ out.Values[i] = ec._Identity_humanId(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ wg.Done()
+ }(i, field)
case "name":
wg.Add(1)
go func(i int, field graphql.CollectedField) {
@@ -4761,6 +4947,33 @@ func (ec *executionContext) _Identity_id(ctx context.Context, field graphql.Coll
}
// nolint: vetshadow
+func (ec *executionContext) _Identity_humanId(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "Identity",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Identity().HumanID(rctx, obj)
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(string)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+ return graphql.MarshalString(res)
+}
+
+// nolint: vetshadow
func (ec *executionContext) _Identity_name(ctx context.Context, field graphql.CollectedField, obj *identity.Interface) graphql.Marshaler {
ctx = ec.Tracer.StartFieldExecution(ctx, field)
defer func() { ec.Tracer.EndFieldExecution(ctx) }()
@@ -4926,6 +5139,316 @@ func (ec *executionContext) _Identity_isProtected(ctx context.Context, field gra
return graphql.MarshalBoolean(res)
}
+var identityConnectionImplementors = []string{"IdentityConnection"}
+
+// nolint: gocyclo, errcheck, gas, goconst
+func (ec *executionContext) _IdentityConnection(ctx context.Context, sel ast.SelectionSet, obj *models.IdentityConnection) graphql.Marshaler {
+ fields := graphql.CollectFields(ctx, sel, identityConnectionImplementors)
+
+ out := graphql.NewOrderedMap(len(fields))
+ invalid := false
+ for i, field := range fields {
+ out.Keys[i] = field.Alias
+
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("IdentityConnection")
+ case "edges":
+ out.Values[i] = ec._IdentityConnection_edges(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ case "nodes":
+ out.Values[i] = ec._IdentityConnection_nodes(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ case "pageInfo":
+ out.Values[i] = ec._IdentityConnection_pageInfo(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ case "totalCount":
+ out.Values[i] = ec._IdentityConnection_totalCount(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+
+ if invalid {
+ return graphql.Null
+ }
+ return out
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _IdentityConnection_edges(ctx context.Context, field graphql.CollectedField, obj *models.IdentityConnection) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "IdentityConnection",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Edges, nil
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.([]models.IdentityEdge)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ arr1 := make(graphql.Array, len(res))
+ var wg sync.WaitGroup
+
+ isLen1 := len(res) == 1
+ if !isLen1 {
+ wg.Add(len(res))
+ }
+
+ for idx1 := range res {
+ idx1 := idx1
+ rctx := &graphql.ResolverContext{
+ Index: &idx1,
+ Result: &res[idx1],
+ }
+ ctx := graphql.WithResolverContext(ctx, rctx)
+ f := func(idx1 int) {
+ if !isLen1 {
+ defer wg.Done()
+ }
+ arr1[idx1] = func() graphql.Marshaler {
+
+ return ec._IdentityEdge(ctx, field.Selections, &res[idx1])
+ }()
+ }
+ if isLen1 {
+ f(idx1)
+ } else {
+ go f(idx1)
+ }
+
+ }
+ wg.Wait()
+ return arr1
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _IdentityConnection_nodes(ctx context.Context, field graphql.CollectedField, obj *models.IdentityConnection) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "IdentityConnection",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Nodes, nil
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.([]identity.Interface)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ arr1 := make(graphql.Array, len(res))
+ var wg sync.WaitGroup
+
+ isLen1 := len(res) == 1
+ if !isLen1 {
+ wg.Add(len(res))
+ }
+
+ for idx1 := range res {
+ idx1 := idx1
+ rctx := &graphql.ResolverContext{
+ Index: &idx1,
+ Result: &res[idx1],
+ }
+ ctx := graphql.WithResolverContext(ctx, rctx)
+ f := func(idx1 int) {
+ if !isLen1 {
+ defer wg.Done()
+ }
+ arr1[idx1] = func() graphql.Marshaler {
+
+ return ec._Identity(ctx, field.Selections, &res[idx1])
+ }()
+ }
+ if isLen1 {
+ f(idx1)
+ } else {
+ go f(idx1)
+ }
+
+ }
+ wg.Wait()
+ return arr1
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _IdentityConnection_pageInfo(ctx context.Context, field graphql.CollectedField, obj *models.IdentityConnection) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "IdentityConnection",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.PageInfo, nil
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(models.PageInfo)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ return ec._PageInfo(ctx, field.Selections, &res)
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _IdentityConnection_totalCount(ctx context.Context, field graphql.CollectedField, obj *models.IdentityConnection) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "IdentityConnection",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.TotalCount, nil
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(int)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+ return graphql.MarshalInt(res)
+}
+
+var identityEdgeImplementors = []string{"IdentityEdge"}
+
+// nolint: gocyclo, errcheck, gas, goconst
+func (ec *executionContext) _IdentityEdge(ctx context.Context, sel ast.SelectionSet, obj *models.IdentityEdge) graphql.Marshaler {
+ fields := graphql.CollectFields(ctx, sel, identityEdgeImplementors)
+
+ out := graphql.NewOrderedMap(len(fields))
+ invalid := false
+ for i, field := range fields {
+ out.Keys[i] = field.Alias
+
+ switch field.Name {
+ case "__typename":
+ out.Values[i] = graphql.MarshalString("IdentityEdge")
+ case "cursor":
+ out.Values[i] = ec._IdentityEdge_cursor(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ case "node":
+ out.Values[i] = ec._IdentityEdge_node(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ default:
+ panic("unknown field " + strconv.Quote(field.Name))
+ }
+ }
+
+ if invalid {
+ return graphql.Null
+ }
+ return out
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _IdentityEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *models.IdentityEdge) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "IdentityEdge",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Cursor, nil
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(string)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+ return graphql.MarshalString(res)
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _IdentityEdge_node(ctx context.Context, field graphql.CollectedField, obj *models.IdentityEdge) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "IdentityEdge",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return obj.Node, nil
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(identity.Interface)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ return ec._Identity(ctx, field.Selections, &res)
+}
+
var labelChangeOperationImplementors = []string{"LabelChangeOperation", "Operation", "Authored"}
// nolint: gocyclo, errcheck, gas, goconst
@@ -6313,6 +6836,27 @@ func (ec *executionContext) _Repository(ctx context.Context, sel ast.SelectionSe
out.Values[i] = ec._Repository_bug(ctx, field, obj)
wg.Done()
}(i, field)
+ case "allIdentities":
+ wg.Add(1)
+ go func(i int, field graphql.CollectedField) {
+ out.Values[i] = ec._Repository_allIdentities(ctx, field, obj)
+ if out.Values[i] == graphql.Null {
+ invalid = true
+ }
+ wg.Done()
+ }(i, field)
+ case "identity":
+ wg.Add(1)
+ go func(i int, field graphql.CollectedField) {
+ out.Values[i] = ec._Repository_identity(ctx, field, obj)
+ wg.Done()
+ }(i, field)
+ case "userIdentity":
+ wg.Add(1)
+ go func(i int, field graphql.CollectedField) {
+ out.Values[i] = ec._Repository_userIdentity(ctx, field, obj)
+ wg.Done()
+ }(i, field)
default:
panic("unknown field " + strconv.Quote(field.Name))
}
@@ -6393,6 +6937,104 @@ func (ec *executionContext) _Repository_bug(ctx context.Context, field graphql.C
return ec._Bug(ctx, field.Selections, res)
}
+// nolint: vetshadow
+func (ec *executionContext) _Repository_allIdentities(ctx context.Context, field graphql.CollectedField, obj *models.Repository) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rawArgs := field.ArgumentMap(ec.Variables)
+ args, err := field_Repository_allIdentities_args(rawArgs)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ rctx := &graphql.ResolverContext{
+ Object: "Repository",
+ Args: args,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().AllIdentities(rctx, obj, args["after"].(*string), args["before"].(*string), args["first"].(*int), args["last"].(*int))
+ })
+ if resTmp == nil {
+ if !ec.HasError(rctx) {
+ ec.Errorf(ctx, "must not be null")
+ }
+ return graphql.Null
+ }
+ res := resTmp.(models.IdentityConnection)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ return ec._IdentityConnection(ctx, field.Selections, &res)
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _Repository_identity(ctx context.Context, field graphql.CollectedField, obj *models.Repository) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rawArgs := field.ArgumentMap(ec.Variables)
+ args, err := field_Repository_identity_args(rawArgs)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ rctx := &graphql.ResolverContext{
+ Object: "Repository",
+ Args: args,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().Identity(rctx, obj, args["prefix"].(string))
+ })
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*identity.Interface)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ if res == nil {
+ return graphql.Null
+ }
+
+ return ec._Identity(ctx, field.Selections, res)
+}
+
+// nolint: vetshadow
+func (ec *executionContext) _Repository_userIdentity(ctx context.Context, field graphql.CollectedField, obj *models.Repository) graphql.Marshaler {
+ ctx = ec.Tracer.StartFieldExecution(ctx, field)
+ defer func() { ec.Tracer.EndFieldExecution(ctx) }()
+ rctx := &graphql.ResolverContext{
+ Object: "Repository",
+ Args: nil,
+ Field: field,
+ }
+ ctx = graphql.WithResolverContext(ctx, rctx)
+ ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx)
+ resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Repository().UserIdentity(rctx, obj)
+ })
+ if resTmp == nil {
+ return graphql.Null
+ }
+ res := resTmp.(*identity.Interface)
+ rctx.Result = res
+ ctx = ec.Tracer.StartFieldChildExecution(ctx)
+
+ if res == nil {
+ return graphql.Null
+ }
+
+ return ec._Identity(ctx, field.Selections, res)
+}
+
var setStatusOperationImplementors = []string{"SetStatusOperation", "Operation", "Authored"}
// nolint: gocyclo, errcheck, gas, goconst
@@ -8987,7 +9629,9 @@ enum Status {
}
type Bug {
+ """The identifier for this bug"""
id: String!
+ """The human version (truncated) identifier for this bug"""
humanId: String!
status: Status!
title: String!
@@ -9049,26 +9693,13 @@ type BugEdge {
node: Bug!
}
-type Repository {
- allBugs(
- """Returns the elements in the list that come after the specified cursor."""
- after: String
- """Returns the elements in the list that come before the specified cursor."""
- before: String
- """Returns the first _n_ elements from the list."""
- first: Int
- """Returns the last _n_ elements from the list."""
- last: Int
- """A query to select and order bugs"""
- query: String
- ): BugConnection!
- bug(prefix: String!): Bug
-}
`},
&ast.Source{Name: "schema/identity.graphql", Input: `"""Represents an identity"""
type Identity {
"""The identifier for this identity"""
id: String!
+ """The human version (truncated) identifier for this identity"""
+ humanId: String!
"""The name of the person, if known."""
name: String
"""The email of the person, if known."""
@@ -9082,6 +9713,18 @@ type Identity {
"""isProtected is true if the chain of git commits started to be signed.
If that's the case, only signed commit with a valid key for this identity can be added."""
isProtected: Boolean!
+}
+
+type IdentityConnection {
+ edges: [IdentityEdge!]!
+ nodes: [Identity!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+type IdentityEdge {
+ cursor: String!
+ node: Identity!
}`},
&ast.Source{Name: "schema/operations.graphql", Input: `"""An operation applied to a bug."""
interface Operation {
@@ -9184,29 +9827,42 @@ type LabelChangeOperation implements Operation & Authored {
removed: [Label!]!
}
`},
- &ast.Source{Name: "schema/root.graphql", Input: `scalar Time
-scalar Label
-scalar Hash
-
-"""Information about pagination in a connection."""
-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: String!
- """When paginating forwards, the cursor to continue."""
- endCursor: String!
-}
-
-"""An object that has an author."""
-interface Authored {
- """The author of this object."""
- author: Identity!
-}
-
-type Query {
+ &ast.Source{Name: "schema/repository.graphql", Input: `
+type Repository {
+ """All the bugs"""
+ allBugs(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ """A query to select and order bugs"""
+ query: String
+ ): BugConnection!
+
+ bug(prefix: String!): Bug
+
+ """All the identities"""
+ allIdentities(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ ): IdentityConnection!
+
+ identity(prefix: String!):Identity
+
+ """The identity created or selected by the user as its own"""
+ userIdentity:Identity
+}`},
+ &ast.Source{Name: "schema/root.graphql", Input: `type Query {
defaultRepository: Repository
repository(id: String!): Repository
}
@@ -9310,4 +9966,25 @@ type SetTitleTimelineItem implements TimelineItem {
was: String!
}
`},
+ &ast.Source{Name: "schema/types.graphql", Input: `scalar Time
+scalar Label
+scalar Hash
+
+"""Information about pagination in a connection."""
+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: String!
+ """When paginating forwards, the cursor to continue."""
+ endCursor: String!
+}
+
+"""An object that has an author."""
+interface Authored {
+ """The author of this object."""
+ author: Identity!
+}`},
)
diff --git a/graphql/models/edges.go b/graphql/models/edges.go
index 1dc42583..4bf10fd3 100644
--- a/graphql/models/edges.go
+++ b/graphql/models/edges.go
@@ -19,3 +19,8 @@ func (e CommentEdge) GetCursor() string {
func (e TimelineItemEdge) GetCursor() string {
return e.Cursor
}
+
+// GetCursor return the cursor entry of an edge
+func (e IdentityEdge) GetCursor() string {
+ return e.Cursor
+}
diff --git a/graphql/models/gen_models.go b/graphql/models/gen_models.go
index 71a6b78b..172fe033 100644
--- a/graphql/models/gen_models.go
+++ b/graphql/models/gen_models.go
@@ -8,6 +8,7 @@ import (
"strconv"
"github.com/MichaelMure/git-bug/bug"
+ "github.com/MichaelMure/git-bug/identity"
)
// An object that has an author.
@@ -41,6 +42,18 @@ type CommentEdge struct {
Node bug.Comment `json:"node"`
}
+type IdentityConnection struct {
+ Edges []IdentityEdge `json:"edges"`
+ Nodes []identity.Interface `json:"nodes"`
+ PageInfo PageInfo `json:"pageInfo"`
+ TotalCount int `json:"totalCount"`
+}
+
+type IdentityEdge struct {
+ Cursor string `json:"cursor"`
+ Node identity.Interface `json:"node"`
+}
+
// The connection type for an Operation
type OperationConnection struct {
Edges []OperationEdge `json:"edges"`
diff --git a/graphql/resolvers/bug.go b/graphql/resolvers/bug.go
index 76eed55d..7af04934 100644
--- a/graphql/resolvers/bug.go
+++ b/graphql/resolvers/bug.go
@@ -6,9 +6,12 @@ import (
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/graphql/connections"
+ "github.com/MichaelMure/git-bug/graphql/graph"
"github.com/MichaelMure/git-bug/graphql/models"
)
+var _ graph.BugResolver = &bugResolver{}
+
type bugResolver struct{}
func (bugResolver) Status(ctx context.Context, obj *bug.Snapshot) (models.Status, error) {
@@ -39,7 +42,7 @@ func (bugResolver) Comments(ctx context.Context, obj *bug.Snapshot, after *strin
}, nil
}
- return connections.BugCommentCon(obj.Comments, edger, conMaker, input)
+ return connections.CommentCon(obj.Comments, edger, conMaker, input)
}
func (bugResolver) Operations(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.OperationConnection, error) {
@@ -66,7 +69,7 @@ func (bugResolver) Operations(ctx context.Context, obj *bug.Snapshot, after *str
}, nil
}
- return connections.BugOperationCon(obj.Operations, edger, conMaker, input)
+ return connections.OperationCon(obj.Operations, edger, conMaker, input)
}
func (bugResolver) Timeline(ctx context.Context, obj *bug.Snapshot, after *string, before *string, first *int, last *int) (models.TimelineItemConnection, error) {
@@ -93,7 +96,7 @@ func (bugResolver) Timeline(ctx context.Context, obj *bug.Snapshot, after *strin
}, nil
}
- return connections.BugTimelineItemCon(obj.Timeline, edger, conMaker, input)
+ return connections.TimelineItemCon(obj.Timeline, edger, conMaker, input)
}
func (bugResolver) LastEdit(ctx context.Context, obj *bug.Snapshot) (time.Time, error) {
diff --git a/graphql/resolvers/identity.go b/graphql/resolvers/identity.go
index d4f9bba2..05f7207e 100644
--- a/graphql/resolvers/identity.go
+++ b/graphql/resolvers/identity.go
@@ -3,15 +3,22 @@ package resolvers
import (
"context"
+ "github.com/MichaelMure/git-bug/graphql/graph"
"github.com/MichaelMure/git-bug/identity"
)
+var _ graph.IdentityResolver = &identityResolver{}
+
type identityResolver struct{}
func (identityResolver) ID(ctx context.Context, obj *identity.Interface) (string, error) {
return (*obj).Id(), nil
}
+func (identityResolver) HumanID(ctx context.Context, obj *identity.Interface) (string, error) {
+ return (*obj).HumanId(), nil
+}
+
func (identityResolver) Name(ctx context.Context, obj *identity.Interface) (*string, error) {
return nilIfEmpty((*obj).Name())
}
diff --git a/graphql/resolvers/mutation.go b/graphql/resolvers/mutation.go
index be6956af..73d39da8 100644
--- a/graphql/resolvers/mutation.go
+++ b/graphql/resolvers/mutation.go
@@ -5,9 +5,12 @@ import (
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/graphql/graph"
"github.com/MichaelMure/git-bug/util/git"
)
+var _ graph.MutationResolver = &mutationResolver{}
+
type mutationResolver struct {
cache *cache.MultiRepoCache
}
diff --git a/graphql/resolvers/query.go b/graphql/resolvers/query.go
index b5763b72..80b5a896 100644
--- a/graphql/resolvers/query.go
+++ b/graphql/resolvers/query.go
@@ -4,9 +4,12 @@ import (
"context"
"github.com/MichaelMure/git-bug/cache"
+ "github.com/MichaelMure/git-bug/graphql/graph"
"github.com/MichaelMure/git-bug/graphql/models"
)
+var _ graph.QueryResolver = &rootQueryResolver{}
+
type rootQueryResolver struct {
cache *cache.MultiRepoCache
}
diff --git a/graphql/resolvers/repo.go b/graphql/resolvers/repo.go
index c696ff34..9003fbf9 100644
--- a/graphql/resolvers/repo.go
+++ b/graphql/resolvers/repo.go
@@ -6,9 +6,13 @@ import (
"github.com/MichaelMure/git-bug/bug"
"github.com/MichaelMure/git-bug/cache"
"github.com/MichaelMure/git-bug/graphql/connections"
+ "github.com/MichaelMure/git-bug/graphql/graph"
"github.com/MichaelMure/git-bug/graphql/models"
+ "github.com/MichaelMure/git-bug/identity"
)
+var _ graph.RepositoryResolver = &repoResolver{}
+
type repoResolver struct{}
func (repoResolver) AllBugs(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, queryStr *string) (models.BugConnection, error) {
@@ -70,7 +74,7 @@ func (repoResolver) AllBugs(ctx context.Context, obj *models.Repository, after *
}, nil
}
- return connections.StringCon(source, edger, conMaker, input)
+ return connections.LazyBugCon(source, edger, conMaker, input)
}
func (repoResolver) Bug(ctx context.Context, obj *models.Repository, prefix string) (*bug.Snapshot, error) {
@@ -82,3 +86,78 @@ func (repoResolver) Bug(ctx context.Context, obj *models.Repository, prefix stri
return b.Snapshot(), nil
}
+
+func (repoResolver) AllIdentities(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (models.IdentityConnection, error) {
+ input := models.ConnectionInput{
+ Before: before,
+ After: after,
+ First: first,
+ Last: last,
+ }
+
+ // Simply pass a []string with the ids to the pagination algorithm
+ source := obj.Repo.AllIdentityIds()
+
+ // The edger create a custom edge holding just the id
+ edger := func(id string, offset int) connections.Edge {
+ return connections.LazyIdentityEdge{
+ Id: id,
+ Cursor: connections.OffsetToCursor(offset),
+ }
+ }
+
+ // The conMaker will finally load and compile identities from git to replace the selected edges
+ conMaker := func(lazyIdentityEdges []connections.LazyIdentityEdge, lazyNode []string, info models.PageInfo, totalCount int) (models.IdentityConnection, error) {
+ edges := make([]models.IdentityEdge, len(lazyIdentityEdges))
+ nodes := make([]identity.Interface, len(lazyIdentityEdges))
+
+ for k, lazyIdentityEdge := range lazyIdentityEdges {
+ i, err := obj.Repo.ResolveIdentity(lazyIdentityEdge.Id)
+
+ if err != nil {
+ return models.IdentityConnection{}, err
+ }
+
+ ii := identity.Interface(i.Identity)
+
+ edges[k] = models.IdentityEdge{
+ Cursor: lazyIdentityEdge.Cursor,
+ Node: ii,
+ }
+ nodes[k] = ii
+ }
+
+ return models.IdentityConnection{
+ Edges: edges,
+ Nodes: nodes,
+ PageInfo: info,
+ TotalCount: totalCount,
+ }, nil
+ }
+
+ return connections.LazyIdentityCon(source, edger, conMaker, input)
+}
+
+func (repoResolver) Identity(ctx context.Context, obj *models.Repository, prefix string) (*identity.Interface, error) {
+ i, err := obj.Repo.ResolveIdentityPrefix(prefix)
+
+ if err != nil {
+ return nil, err
+ }
+
+ ii := identity.Interface(i.Identity)
+
+ return &ii, nil
+}
+
+func (repoResolver) UserIdentity(ctx context.Context, obj *models.Repository) (*identity.Interface, error) {
+ i, err := obj.Repo.GetUserIdentity()
+
+ if err != nil {
+ return nil, err
+ }
+
+ ii := identity.Interface(i.Identity)
+
+ return &ii, nil
+}
diff --git a/graphql/resolvers/root.go b/graphql/resolvers/root.go
index cfdfe346..7414a097 100644
--- a/graphql/resolvers/root.go
+++ b/graphql/resolvers/root.go
@@ -6,6 +6,8 @@ import (
"github.com/MichaelMure/git-bug/graphql/graph"
)
+var _ graph.ResolverRoot = &RootResolver{}
+
type RootResolver struct {
cache.MultiRepoCache
}
diff --git a/graphql/schema/bug.graphql b/graphql/schema/bug.graphql
index 7e1c57b5..a1a61e7e 100644
--- a/graphql/schema/bug.graphql
+++ b/graphql/schema/bug.graphql
@@ -28,7 +28,9 @@ enum Status {
}
type Bug {
+ """The identifier for this bug"""
id: String!
+ """The human version (truncated) identifier for this bug"""
humanId: String!
status: Status!
title: String!
@@ -90,18 +92,3 @@ type BugEdge {
node: Bug!
}
-type Repository {
- allBugs(
- """Returns the elements in the list that come after the specified cursor."""
- after: String
- """Returns the elements in the list that come before the specified cursor."""
- before: String
- """Returns the first _n_ elements from the list."""
- first: Int
- """Returns the last _n_ elements from the list."""
- last: Int
- """A query to select and order bugs"""
- query: String
- ): BugConnection!
- bug(prefix: String!): Bug
-}
diff --git a/graphql/schema/identity.graphql b/graphql/schema/identity.graphql
index 18666f76..6872ecb9 100644
--- a/graphql/schema/identity.graphql
+++ b/graphql/schema/identity.graphql
@@ -2,6 +2,8 @@
type Identity {
"""The identifier for this identity"""
id: String!
+ """The human version (truncated) identifier for this identity"""
+ humanId: String!
"""The name of the person, if known."""
name: String
"""The email of the person, if known."""
@@ -16,3 +18,15 @@ type Identity {
If that's the case, only signed commit with a valid key for this identity can be added."""
isProtected: Boolean!
}
+
+type IdentityConnection {
+ edges: [IdentityEdge!]!
+ nodes: [Identity!]!
+ pageInfo: PageInfo!
+ totalCount: Int!
+}
+
+type IdentityEdge {
+ cursor: String!
+ node: Identity!
+} \ No newline at end of file
diff --git a/graphql/schema/repository.graphql b/graphql/schema/repository.graphql
new file mode 100644
index 00000000..a4f4b424
--- /dev/null
+++ b/graphql/schema/repository.graphql
@@ -0,0 +1,35 @@
+
+type Repository {
+ """All the bugs"""
+ allBugs(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ """A query to select and order bugs"""
+ query: String
+ ): BugConnection!
+
+ bug(prefix: String!): Bug
+
+ """All the identities"""
+ allIdentities(
+ """Returns the elements in the list that come after the specified cursor."""
+ after: String
+ """Returns the elements in the list that come before the specified cursor."""
+ before: String
+ """Returns the first _n_ elements from the list."""
+ first: Int
+ """Returns the last _n_ elements from the list."""
+ last: Int
+ ): IdentityConnection!
+
+ identity(prefix: String!):Identity
+
+ """The identity created or selected by the user as its own"""
+ userIdentity:Identity
+} \ No newline at end of file
diff --git a/graphql/schema/root.graphql b/graphql/schema/root.graphql
index 7b43366f..2d430aa5 100644
--- a/graphql/schema/root.graphql
+++ b/graphql/schema/root.graphql
@@ -1,25 +1,3 @@
-scalar Time
-scalar Label
-scalar Hash
-
-"""Information about pagination in a connection."""
-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: String!
- """When paginating forwards, the cursor to continue."""
- endCursor: String!
-}
-
-"""An object that has an author."""
-interface Authored {
- """The author of this object."""
- author: Identity!
-}
-
type Query {
defaultRepository: Repository
repository(id: String!): Repository
diff --git a/graphql/schema/types.graphql b/graphql/schema/types.graphql
new file mode 100644
index 00000000..2eaa07a2
--- /dev/null
+++ b/graphql/schema/types.graphql
@@ -0,0 +1,21 @@
+scalar Time
+scalar Label
+scalar Hash
+
+"""Information about pagination in a connection."""
+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: String!
+ """When paginating forwards, the cursor to continue."""
+ endCursor: String!
+}
+
+"""An object that has an author."""
+interface Authored {
+ """The author of this object."""
+ author: Identity!
+} \ No newline at end of file
diff --git a/vendor/github.com/99designs/gqlgen/graphql/version.go b/vendor/github.com/99designs/gqlgen/graphql/version.go
index 8cf3c9ba..490ff3ff 100644
--- a/vendor/github.com/99designs/gqlgen/graphql/version.go
+++ b/vendor/github.com/99designs/gqlgen/graphql/version.go
@@ -1,3 +1,3 @@
package graphql
-const Version = "dev"
+const Version = "v0.7.2"
diff --git a/vendor/github.com/99designs/gqlgen/handler/graphql.go b/vendor/github.com/99designs/gqlgen/handler/graphql.go
index eb8880de..7c5f70cf 100644
--- a/vendor/github.com/99designs/gqlgen/handler/graphql.go
+++ b/vendor/github.com/99designs/gqlgen/handler/graphql.go
@@ -7,6 +7,7 @@ import (
"io"
"net/http"
"strings"
+ "time"
"github.com/99designs/gqlgen/complexity"
"github.com/99designs/gqlgen/graphql"
@@ -25,15 +26,16 @@ type params struct {
}
type Config struct {
- cacheSize int
- upgrader websocket.Upgrader
- recover graphql.RecoverFunc
- errorPresenter graphql.ErrorPresenterFunc
- resolverHook graphql.FieldMiddleware
- requestHook graphql.RequestMiddleware
- tracer graphql.Tracer
- complexityLimit int
- disableIntrospection bool
+ cacheSize int
+ upgrader websocket.Upgrader
+ recover graphql.RecoverFunc
+ errorPresenter graphql.ErrorPresenterFunc
+ resolverHook graphql.FieldMiddleware
+ requestHook graphql.RequestMiddleware
+ tracer graphql.Tracer
+ complexityLimit int
+ disableIntrospection bool
+ connectionKeepAlivePingInterval time.Duration
}
func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDocument, op *ast.OperationDefinition, query string, variables map[string]interface{}) *graphql.RequestContext {
@@ -243,6 +245,14 @@ func CacheSize(size int) Option {
const DefaultCacheSize = 1000
+// WebsocketKeepAliveDuration allows you to reconfigure the keepAlive behavior.
+// By default, keep-alive is disabled.
+func WebsocketKeepAliveDuration(duration time.Duration) Option {
+ return func(cfg *Config) {
+ cfg.connectionKeepAlivePingInterval = duration
+ }
+}
+
func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
cfg := &Config{
cacheSize: DefaultCacheSize,
diff --git a/vendor/github.com/99designs/gqlgen/handler/websocket.go b/vendor/github.com/99designs/gqlgen/handler/websocket.go
index dae262bd..09800c17 100644
--- a/vendor/github.com/99designs/gqlgen/handler/websocket.go
+++ b/vendor/github.com/99designs/gqlgen/handler/websocket.go
@@ -8,6 +8,7 @@ import (
"log"
"net/http"
"sync"
+ "time"
"github.com/99designs/gqlgen/graphql"
"github.com/gorilla/websocket"
@@ -27,7 +28,7 @@ const (
dataMsg = "data" // Server -> Client
errorMsg = "error" // Server -> Client
completeMsg = "complete" // Server -> Client
- //connectionKeepAliveMsg = "ka" // Server -> Client TODO: keepalives
+ connectionKeepAliveMsg = "ka" // Server -> Client
)
type operationMessage struct {
@@ -37,12 +38,13 @@ type operationMessage struct {
}
type wsConnection struct {
- ctx context.Context
- conn *websocket.Conn
- exec graphql.ExecutableSchema
- active map[string]context.CancelFunc
- mu sync.Mutex
- cfg *Config
+ ctx context.Context
+ conn *websocket.Conn
+ exec graphql.ExecutableSchema
+ active map[string]context.CancelFunc
+ mu sync.Mutex
+ cfg *Config
+ keepAliveTicker *time.Ticker
initPayload InitPayload
}
@@ -109,6 +111,20 @@ func (c *wsConnection) write(msg *operationMessage) {
}
func (c *wsConnection) run() {
+ // We create a cancellation that will shutdown the keep-alive when we leave
+ // this function.
+ ctx, cancel := context.WithCancel(c.ctx)
+ defer cancel()
+
+ // Create a timer that will fire every interval to keep the connection alive.
+ if c.cfg.connectionKeepAlivePingInterval != 0 {
+ c.mu.Lock()
+ c.keepAliveTicker = time.NewTicker(c.cfg.connectionKeepAlivePingInterval)
+ c.mu.Unlock()
+
+ go c.keepAlive(ctx)
+ }
+
for {
message := c.readOp()
if message == nil {
@@ -141,6 +157,18 @@ func (c *wsConnection) run() {
}
}
+func (c *wsConnection) keepAlive(ctx context.Context) {
+ for {
+ select {
+ case <-ctx.Done():
+ c.keepAliveTicker.Stop()
+ return
+ case <-c.keepAliveTicker.C:
+ c.write(&operationMessage{Type: connectionKeepAliveMsg})
+ }
+ }
+}
+
func (c *wsConnection) subscribe(message *operationMessage) bool {
var reqParams params
if err := jsonDecode(bytes.NewReader(message.Payload), &reqParams); err != nil {