diff --git a/query.go b/query.go index e10b771..06c21a8 100644 --- a/query.go +++ b/query.go @@ -10,20 +10,55 @@ import ( "github.com/shurcooL/graphql/ident" ) +type NamedOperation struct { + Name string + Document interface{} +} + +func NewNamedOperation(name string, v interface{}) *NamedOperation { + return &NamedOperation{ + Name: name, + Document: v, + } +} + +func deconstructOperation(v interface{}) (string, interface{}) { + if named, ok := v.(*NamedOperation); ok { + return named.Name, named.Document + } + return "", v +} + func constructQuery(v interface{}, variables map[string]interface{}) string { - query := query(v) + queryName, queryDoc := deconstructOperation(v) + query := query(queryDoc) + + queryPrefix := "query" + if queryName != "" { + queryPrefix = "query " + queryName + } + if len(variables) > 0 { - return "query(" + queryArguments(variables) + ")" + query + return queryPrefix + "(" + queryArguments(variables) + ")" + query + } else if queryName != "" { + return queryPrefix + query } return query } func constructMutation(v interface{}, variables map[string]interface{}) string { - query := query(v) + mutationName, queryDoc := deconstructOperation(v) + query := query(queryDoc) + + mutationPrefix := "mutation" + if mutationName != "" { + mutationPrefix = "mutation " + mutationName + } + if len(variables) > 0 { - return "mutation(" + queryArguments(variables) + ")" + query + return mutationPrefix + "(" + queryArguments(variables) + ")" + query } - return "mutation" + query + return mutationPrefix + query } // queryArguments constructs a minified arguments string for variables. diff --git a/query_test.go b/query_test.go index 4de8cb5..e1972e6 100644 --- a/query_test.go +++ b/query_test.go @@ -227,6 +227,20 @@ func TestConstructQuery(t *testing.T) { }{}, want: `{viewer{login,createdAt,id,databaseId}}`, }, + { + inV: NewNamedOperation("FindPerson", struct { + Login string + }{}), + inVariables: nil, + want: `query FindPerson{login}`, + }, + { + inV: NewNamedOperation("FindPerson", struct { + Login string + }{}), + inVariables: map[string]interface{}{"id": Int(1)}, + want: `query FindPerson($id:Int!){login}`, + }, } for _, tc := range tests { got := constructQuery(tc.inV, tc.inVariables) @@ -262,6 +276,24 @@ func TestConstructMutation(t *testing.T) { }, want: `mutation($input:AddReactionInput!){addReaction(input:$input){subject{reactionGroups{users{totalCount}}}}}`, }, + { + inV: NewNamedOperation("ThumbsUp", struct { + AddReaction struct { + Name string + } `graphql:"addReaction(input:$input)"` + }{}), + inVariables: nil, + want: `mutation ThumbsUp{addReaction(input:$input){name}}`, + }, + { + inV: NewNamedOperation("ThumbsUp", struct { + AddReaction struct { + Name string + } `graphql:"addReaction(input:$input)"` + }{}), + inVariables: map[string]interface{}{"id": Int(1)}, + want: `mutation ThumbsUp($id:Int!){addReaction(input:$input){name}}`, + }, } for _, tc := range tests { got := constructMutation(tc.inV, tc.inVariables)