Skip to content

Commit

Permalink
add subscription Exec alias for pre-built query (shurcooL#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
hgiasac authored Jun 10, 2022
1 parent d4051ab commit 391115f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 23 deletions.
58 changes: 35 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ For more information, see package [`github.com/shurcooL/githubv4`](https://githu
- [Specify GraphQL type name](#specify-graphql-type-name)
- [Mutations](#mutations)
- [Mutations Without Fields](#mutations-without-fields)
- [Execute](#execute)
- [Subscription](#subscription)
- [Usage](#usage-1)
- [Subscribe](#subscribe)
Expand All @@ -35,6 +34,7 @@ For more information, see package [`github.com/shurcooL/githubv4`](https://githu
- [Custom HTTP Client](#custom-http-client)
- [Custom WebSocket client](#custom-websocket-client)
- [Options](#options-1)
- [Execute pre-built query](#execute-pre-built-query)
- [With operation name (deprecated)](#with-operation-name-deprecated)
- [Raw bytes response](#raw-bytes-response)
- [Multiple mutations with ordered map](#multiple-mutations-with-ordered-map)
Expand Down Expand Up @@ -435,28 +435,6 @@ fmt.Printf("Created a review: %s.\n", m.CreateReview)
// Created a review: .
```
### Execute
The `Exec` function allows you to executing pre-built queries. While using reflection to build queries is convenient as you get some resemblance of type safety, it gets very cumbersome when you need to create queries semi-dynamically. For instance, imagine you are building a CLI tool to query data from a graphql endpoint and you want users to be able to narrow down the query by passing cli flags or something.
```Go
// filters would be built dynamically somehow from the command line flags
filters := []string{
`fieldA: {subfieldA: {_eq: "a"}}`,
`fieldB: {_eq: "b"}`,
...
}

query := "query{something(where: {" + strings.Join(filters, ", ") + "}){id}}"
res := struct {
Somethings []Something
}{}

if err := client.Exec(ctx, query, &res, map[string]any{}); err != nil {
panic(err)
}
```
### Subscription
#### Usage
Expand Down Expand Up @@ -682,6 +660,40 @@ func (cd cachedDirective) String() string {
client.Query(ctx, &q, variables, graphql.OperationName("MyQuery"), cachedDirective{})
```
### Execute pre-built query
The `Exec` function allows you to executing pre-built queries. While using reflection to build queries is convenient as you get some resemblance of type safety, it gets very cumbersome when you need to create queries semi-dynamically. For instance, imagine you are building a CLI tool to query data from a graphql endpoint and you want users to be able to narrow down the query by passing cli flags or something.
```Go
// filters would be built dynamically somehow from the command line flags
filters := []string{
`fieldA: {subfieldA: {_eq: "a"}}`,
`fieldB: {_eq: "b"}`,
...
}

query := "query{something(where: {" + strings.Join(filters, ", ") + "}){id}}"
res := struct {
Somethings []Something
}{}

if err := client.Exec(ctx, query, &res, map[string]any{}); err != nil {
panic(err)
}

subscription := "subscription{something(where: {" + strings.Join(filters, ", ") + "}){id}}"
subscriptionId, err := subscriptionClient.Exec(subscription, nil, func(dataValue *json.RawMessage, errValue error) error {
if errValue != nil {
// handle error
// if returns error, it will failback to `onError` event
return nil
}
data := query{}
err := json.Unmarshal(dataValue, &data)
// ...
})
```
### With operation name (deprecated)
Operation name is still on API decision plan https://github.com/shurcooL/graphql/issues/12. However, in my opinion separate methods are easier choice to avoid breaking changes
Expand Down
6 changes: 6 additions & 0 deletions subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,16 @@ func (sc *SubscriptionClient) NamedSubscribe(name string, v interface{}, variabl
}

// SubscribeRaw sends start message to server and open a channel to receive data, with raw query
// Deprecated: use Exec instead
func (sc *SubscriptionClient) SubscribeRaw(query string, variables map[string]interface{}, handler func(message *json.RawMessage, err error) error) (string, error) {
return sc.doRaw(query, variables, handler)
}

// Exec sends start message to server and open a channel to receive data, with raw query
func (sc *SubscriptionClient) Exec(query string, variables map[string]interface{}, handler func(message *json.RawMessage, err error) error) (string, error) {
return sc.doRaw(query, variables, handler)
}

func (sc *SubscriptionClient) do(v interface{}, variables map[string]interface{}, handler func(message *json.RawMessage, err error) error, options ...Option) (string, error) {
query, err := ConstructSubscription(v, variables, options...)
if err != nil {
Expand Down

0 comments on commit 391115f

Please sign in to comment.