Skip to content

Commit

Permalink
Use github.com/shurcooL/graphql package.
Browse files Browse the repository at this point in the history
The general GraphQL client has been factored out into a separate
package. Use it, instead of having an internal copy.

As a result, githubql client implementation becomes very simple,
it just defers to the graphql client, with minor convenience changes
on top.

The graphql package continues to provide useful Go types for the GitHub
GraphQL schema, generated from the schema.
  • Loading branch information
dmitshur committed Jul 23, 2017
1 parent 90ae6ed commit e5a92f9
Show file tree
Hide file tree
Showing 12 changed files with 25 additions and 1,382 deletions.
2 changes: 1 addition & 1 deletion doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
// For now, see README for more details.
package githubql // import "github.com/shurcooL/githubql"

//go:generate go run internal/gen/gen.go
//go:generate go run gen.go
9 changes: 4 additions & 5 deletions internal/gen/gen.go → gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import (
"io/ioutil"
"log"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"text/template"

"github.com/shurcooL/githubql/internal/hacky/caseconv"
"github.com/shurcooL/graphql/ident"
)

func main() {
Expand Down Expand Up @@ -57,7 +56,7 @@ func run() error {
}

func loadSchema() (schema interface{}, err error) {
f, err := os.Open(filepath.Join("internal", "gen", "schema.json"))
f, err := os.Open("schema.json")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -143,8 +142,8 @@ func t(text string) *template.Template {
sort.Strings(names)
return names
},
"identifier": caseconv.LowerCamelCaseToMixedCaps,
"enumIdentifier": caseconv.UpperUnderscoreSepToMixedCaps,
"identifier": func(name string) string { return ident.ParseLowerCamelCase(name).ToMixedCaps() },
"enumIdentifier": func(name string) string { return ident.ParseScreamingSnakeCase(name).ToMixedCaps() },
"type": typeString,
"endSentence": func(s string) string {
s = strings.ToLower(s[0:1]) + s[1:]
Expand Down
87 changes: 5 additions & 82 deletions githubql.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
package githubql

import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/shurcooL/githubql/internal/jsonutil"
"github.com/shurcooL/go/ctxhttp"
"github.com/shurcooL/graphql"
)

// Client is a GitHub GraphQL API v4 client.
type Client struct {
httpClient *http.Client
client *graphql.Client
}

// NewClient creates a new GitHub GraphQL API v4 client with the provided http.Client.
Expand All @@ -22,19 +18,16 @@ type Client struct {
// Note that GitHub GraphQL API v4 requires authentication, so
// the provided http.Client is expected to take care of that.
func NewClient(httpClient *http.Client) *Client {
if httpClient == nil {
httpClient = http.DefaultClient
}
return &Client{
httpClient: httpClient,
client: graphql.NewClient("https://api.github.com/graphql", httpClient, scalars),
}
}

// Query executes a single GraphQL query request,
// with a query derived from q, populating the response into it.
// q should be a pointer to struct that corresponds to the GitHub GraphQL schema.
func (c *Client) Query(ctx context.Context, q interface{}, variables map[string]interface{}) error {
return c.do(ctx, queryOperation, q, variables)
return c.client.Query(ctx, q, variables)
}

// Mutate executes a single GraphQL mutation request,
Expand All @@ -47,75 +40,5 @@ func (c *Client) Mutate(ctx context.Context, m interface{}, input Input, variabl
} else {
variables["input"] = input
}
return c.do(ctx, mutationOperation, m, variables)
}

// do executes a single GraphQL operation.
func (c *Client) do(ctx context.Context, op operationType, v interface{}, variables map[string]interface{}) error {
var query string
switch op {
case queryOperation:
query = constructQuery(v, variables)
case mutationOperation:
query = constructMutation(v, variables)
}
in := struct {
Query string `json:"query"`
Variables map[string]interface{} `json:"variables,omitempty"`
}{
Query: query,
Variables: variables,
}
var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(in)
if err != nil {
return err
}
resp, err := ctxhttp.Post(ctx, c.httpClient, "https://api.github.com/graphql", "application/json", &buf)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status: %v", resp.Status)
}
var out struct {
Data json.RawMessage
Errors errors
//Extensions interface{} // Unused.
}
err = json.NewDecoder(resp.Body).Decode(&out)
if err != nil {
return err
}
if len(out.Errors) > 0 {
return out.Errors
}
err = jsonutil.UnmarshalGraphQL(out.Data, v)
return err
}

// errors represents the "errors" array in a response from a GraphQL server.
// If returned via error interface, the slice is expected to contain at least 1 element.
//
// Specification: https://facebook.github.io/graphql/#sec-Errors.
type errors []struct {
Message string
Locations []struct {
Line int
Column int
}
return c.client.Mutate(ctx, m, variables)
}

// Error implements error interface.
func (e errors) Error() string {
return e[0].Message
}

type operationType uint8

const (
queryOperation operationType = iota
mutationOperation
//subscriptionOperation // Unused.
)
119 changes: 0 additions & 119 deletions hacky.go

This file was deleted.

4 changes: 0 additions & 4 deletions internal/hacky/README.md

This file was deleted.

Loading

0 comments on commit e5a92f9

Please sign in to comment.