Skip to content

Commit

Permalink
Merge branch 'master' into graphql-operation-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac committed Aug 13, 2023
2 parents 80b93d0 + 1956215 commit 5c080fe
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 52 deletions.
18 changes: 11 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ jobs:
test-go:
name: Run Go lint and unit tests
runs-on: ubuntu-20.04
permissions:
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: actions/setup-go@v2
uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: "1.16.4"
- uses: actions/cache@v2
go-version: "1.20"
- uses: actions/cache@v3
with:
path: |
~/go/pkg/mod
Expand All @@ -29,7 +31,9 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Install dependencies
run: go get -t -v ./...
run: |
go get -t -v ./...
go install ./...
- name: Format
run: diff -u <(echo -n) <(gofmt -d -s .)
- name: Vet
Expand All @@ -43,6 +47,7 @@ jobs:
- name: Go coverage format
run: |
go get github.com/boumenot/gocover-cobertura
go install github.com/boumenot/gocover-cobertura
gocover-cobertura < coverage.out > coverage.xml
- name: Code Coverage Summary Report
uses: irongut/[email protected]
Expand All @@ -58,9 +63,8 @@ jobs:
thresholds: "60 80"
- name: Add Coverage PR Comment
uses: marocchino/sticky-pull-request-comment@v2
if: github.event_name == 'pull_request'
if: ${{ github.event_name == 'pull_request_target' }}
with:
recreate: true
path: code-coverage-results.md
- name: Dump docker logs on failure
if: failure()
Expand Down
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ For more information, see package [`github.com/shurcooL/githubv4`](https://githu
- [Directories](#directories)
- [References](#references)
- [License](#license)

## Installation

`go-graphql-client` requires Go version 1.16 or later. For older Go versions, downgrade the library version below v0.7.1.
`go-graphql-client` requires Go version 1.20 or later. For older Go versions:
- **>= 1.16 < 1.20**: downgrade the library to version v0.9.x
- **< 1.16**: downgrade the library version below v0.7.1.

```bash
go get -u github.com/hasura/go-graphql-client
Expand Down Expand Up @@ -202,7 +204,7 @@ var mutation struct {
CreateDimensions struct {
ID string `graphql:"id"`
} `graphql:"create_dimensions(ship_dimensions: $ship_dimensions)"`
}
}

variables := map[string]interface{}{
"ship_dimensions": myDimensions,
Expand Down Expand Up @@ -234,7 +236,7 @@ struct {
// login
// createdAt
// databaseId
// }
// }
// }

struct {
Expand Down Expand Up @@ -559,7 +561,7 @@ client := graphql.NewSubscriptionClient("wss://example.com/graphql").
"authentication": "...",
},
}).
// or lazy parameters with function
// or lazy parameters with function
WithConnectionParamsFn(func () map[string]interface{} {
return map[string]interface{} {
"headers": map[string]string{
Expand All @@ -575,7 +577,7 @@ client := graphql.NewSubscriptionClient("wss://example.com/graphql").
```Go
client.
// write timeout of websocket client
WithTimeout(time.Minute).
WithTimeout(time.Minute).
// When the websocket server was stopped, the client will retry connecting every second until timeout
WithRetryTimeout(time.Minute).
// sets loging function to print out received messages. By default, nothing is printed
Expand All @@ -587,7 +589,7 @@ client.
// the client should exit when all subscriptions were closed, default true
WithExitWhenNoSubscription(false).
// WithRetryStatusCodes allow retry the subscription connection when receiving one of these codes
// the input parameter can be number string or range, e.g 4000-5000
// the input parameter can be number string or range, e.g 4000-5000
WithRetryStatusCodes("4000", "4000-4050")
```
Expand Down Expand Up @@ -796,7 +798,7 @@ var res struct {
Somethings []Something `json:"something"`
}

raw, err := client.ExecRaw(ctx, query, map[string]any{})
raw, err := client.ExecRaw(ctx, query, map[string]any{})
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -942,11 +944,11 @@ func ConstructQuery(v interface{}, variables map[string]interface{}, options ...
func ConstructMutation(v interface{}, variables map[string]interface{}, options ...Option) (string, error)

// ConstructSubscription build GraphQL subscription string from struct and variables
func ConstructSubscription(v interface{}, variables map[string]interface{}, options ...Option) (string, error)
func ConstructSubscription(v interface{}, variables map[string]interface{}, options ...Option) (string, error)

// UnmarshalGraphQL parses the JSON-encoded GraphQL response data and stores
// the result in the GraphQL query data structure pointed to by v.
func UnmarshalGraphQL(data []byte, v interface{}) error
func UnmarshalGraphQL(data []byte, v interface{}) error
```
Directories
Expand Down
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
module github.com/hasura/go-graphql-client

go 1.16
go 1.20

require (
github.com/google/uuid v1.3.0
github.com/graph-gophers/graphql-go v1.5.0
github.com/graph-gophers/graphql-transport-ws v0.0.2
nhooyr.io/websocket v1.8.7
)

require (
github.com/gorilla/websocket v1.5.0 // indirect
github.com/klauspost/compress v1.16.7 // indirect
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
nhooyr.io/websocket v1.8.7
)

replace github.com/gin-gonic/gin v1.6.3 => github.com/gin-gonic/gin v1.7.7
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc=
github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os=
github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eLQin8PtA8xY9eCzjRpvo=
Expand All @@ -40,6 +42,8 @@ github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGn
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
Expand Down
37 changes: 26 additions & 11 deletions graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"

Expand Down Expand Up @@ -105,26 +104,32 @@ func (c *Client) NamedMutateRaw(ctx context.Context, name string, m interface{},
func (c *Client) buildAndRequest(ctx context.Context, op operationType, v interface{}, variables map[string]interface{}, options ...Option) ([]byte, *http.Response, io.Reader, Errors) {
var query string
var err error
var optionOutput *constructOptionsOutput
switch op {
case queryOperation:
query, err = ConstructQuery(v, variables, options...)
query, optionOutput, err = constructQuery(v, variables, options...)
case mutationOperation:
query, err = ConstructMutation(v, variables, options...)
query, optionOutput, err = constructMutation(v, variables, options...)
}

if err != nil {
return nil, nil, nil, Errors{newError(ErrGraphQLEncode, err)}
}

return c.request(ctx, query, variables, options...)
return c.request(ctx, query, variables, optionOutput)
}

// Request the common method that send graphql request
func (c *Client) request(ctx context.Context, query string, variables map[string]interface{}, options ...Option) ([]byte, *http.Response, io.Reader, Errors) {
func (c *Client) request(ctx context.Context, query string, variables map[string]interface{}, options *constructOptionsOutput) ([]byte, *http.Response, io.Reader, Errors) {
in := GraphQLRequestPayload{
Query: query,
Variables: variables,
}

if options != nil {
in.OperationName = options.operationName
}

var buf bytes.Buffer
err := json.NewEncoder(&buf).Encode(in)
if err != nil {
Expand Down Expand Up @@ -173,7 +178,7 @@ func (c *Client) request(ctx context.Context, query string, variables map[string
}

if resp.StatusCode != http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
body, _ := io.ReadAll(resp.Body)
err := newError(ErrRequestError, fmt.Errorf("%v; body: %q", resp.Status, body))

if c.debug {
Expand All @@ -190,7 +195,7 @@ func (c *Client) request(ctx context.Context, query string, variables map[string
// copy the response reader for debugging
var respReader *bytes.Reader
if c.debug {
body, err := ioutil.ReadAll(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, nil, nil, Errors{newError(ErrJsonDecode, err)}
}
Expand Down Expand Up @@ -250,14 +255,24 @@ func (c *Client) do(ctx context.Context, op operationType, v interface{}, variab
// Executes a pre-built query and unmarshals the response into v. Unlike the Query method you have to specify in the query the
// fields that you want to receive as they are not inferred from v. This method is useful if you need to build the query dynamically.
func (c *Client) Exec(ctx context.Context, query string, v interface{}, variables map[string]interface{}, options ...Option) error {
data, resp, respBuf, errs := c.request(ctx, query, variables, options...)
optionsOutput, err := constructOptions(options)
if err != nil {
return err
}

data, resp, respBuf, errs := c.request(ctx, query, variables, optionsOutput)
return c.processResponse(v, data, resp, respBuf, errs)
}

// Executes a pre-built query and returns the raw json message. Unlike the Query method you have to specify in the query the
// fields that you want to receive as they are not inferred from the interface. This method is useful if you need to build the query dynamically.
func (c *Client) ExecRaw(ctx context.Context, query string, variables map[string]interface{}, options ...Option) ([]byte, error) {
data, _, _, errs := c.request(ctx, query, variables, options...)
optionsOutput, err := constructOptions(options)
if err != nil {
return nil, err
}

data, _, _, errs := c.request(ctx, query, variables, optionsOutput)
if len(errs) > 0 {
return data, errs
}
Expand Down Expand Up @@ -356,7 +371,7 @@ func newError(code string, err error) Error {

func (e Error) withRequest(req *http.Request, bodyReader io.Reader) Error {
internal := e.getInternalExtension()
bodyBytes, err := ioutil.ReadAll(bodyReader)
bodyBytes, err := io.ReadAll(bodyReader)
if err != nil {
internal["error"] = err
} else {
Expand All @@ -375,7 +390,7 @@ func (e Error) withRequest(req *http.Request, bodyReader io.Reader) Error {

func (e Error) withResponse(res *http.Response, bodyReader io.Reader) Error {
internal := e.getInternalExtension()
bodyBytes, err := ioutil.ReadAll(bodyReader)
bodyBytes, err := io.ReadAll(bodyReader)
if err != nil {
internal["error"] = err
} else {
Expand Down
3 changes: 1 addition & 2 deletions graphql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
Expand Down Expand Up @@ -427,7 +426,7 @@ func (l localRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
}

func mustRead(r io.Reader) string {
b, err := ioutil.ReadAll(r)
b, err := io.ReadAll(r)
if err != nil {
panic(err)
}
Expand Down
14 changes: 8 additions & 6 deletions pkg/jsonutil/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,15 @@ func (d *decoder) decode() error {
if v.Kind() == reflect.Slice {
// we want to append the template item copy
// so that all the inner structure gets preserved
copied, err := copyTemplate(v.Index(0))
if err != nil {
return fmt.Errorf("failed to copy template: %w", err)
if v.Len() != 0 {
copied, err := copyTemplate(v.Index(0))
if err != nil {
return fmt.Errorf("failed to copy template: %w", err)
}
v.Set(reflect.Append(v, copied)) // v = append(v, T).
f = v.Index(v.Len() - 1)
someSliceExist = true
}
v.Set(reflect.Append(v, copied)) // v = append(v, T).
f = v.Index(v.Len() - 1)
someSliceExist = true
}
d.vs[i] = append(d.vs[i], f)
}
Expand Down
Loading

0 comments on commit 5c080fe

Please sign in to comment.