### Install go-graphql-client Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Use this command to install the go-graphql-client package. Ensure you are using Go version 1.23 or later. ```bash go get -u github.com/hasura/go-graphql-client ``` -------------------------------- ### Install Server Dependencies Source: https://github.com/hasura/go-graphql-client/blob/master/example/graphql-ws-bc/README.md Installs the necessary Node.js dependencies for the GraphQL server. This command should be run from the 'server' directory. ```bash cd server npm install npm start ``` -------------------------------- ### Run Go Client with subscriptions-transport-ws Source: https://github.com/hasura/go-graphql-client/blob/master/example/hasura/README.md Execute this command to run the Go client example that uses the subscriptions-transport-ws protocol for subscriptions. Ensure the client directory is correctly set up. ```sh go run ./client/subscriptions-transport-ws ``` -------------------------------- ### Run Go Client with graphql-ws Protocol Source: https://github.com/hasura/go-graphql-client/blob/master/example/hasura/README.md Execute this command to run the Go client example that uses the graphql-ws protocol for subscriptions. Ensure the client directory is correctly set up. ```sh go run ./client/graphql-ws ``` -------------------------------- ### Run Hasura GraphQL Server with Docker Compose Source: https://github.com/hasura/go-graphql-client/blob/master/example/hasura/README.md Use this command to start the Hasura GraphQL server in detached mode. Ensure Docker and Docker Compose are installed. ```sh docker-compose up -d ``` -------------------------------- ### Execute Query and Get Raw Extensions Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Executes a query and returns both the raw data and the extensions map separately. Useful for inspecting extension details. ```go query := `query{something(where: { foo: { _eq: "bar" }}){id}}` data, extensions, err := client.ExecRawWithExtensions(ctx, query, map[string]any{}) if err != nil { panic(err) } // You can now use the `extensions` variable to access the extensions data fmt.Println("Extensions:", extensions) ``` -------------------------------- ### GraphQL Mutation Example with Ordered Map Source: https://github.com/hasura/go-graphql-client/blob/master/README.md For making multiple mutations in a single query, use an ordered map `[][2]interface{}` instead of structs for convenience. This example demonstrates creating multiple users. ```GraphQL mutation($login1: String!, $login2: String!, $login3: String!) { createUser(login: $login1) { login } createUser(login: $login2) { login } createUser(login: $login3) { login } } variables { "login1": "grihabor", "login2": "diman", "login3": "indigo" } ``` ```Go type CreateUser struct { Login string } m := [][2]interface{}{ {"createUser(login: $login1)", &CreateUser{}}, {"createUser(login: $login2)", &CreateUser{}}, {"createUser(login: $login3)", &CreateUser{}}, } variables := map[string]interface{}{ "login1": "grihabor", "login2": "diman", "login3": "indigo", } ``` -------------------------------- ### Replace Default WebSocket Client Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Use the `WithWebSocket` method to replace the default WebSocket client constructor with a custom implementation that satisfies the `WebsocketConn` interface. This example shows how to integrate with the `coder/websocket` library. ```go // WithWebSocket replaces customized websocket client constructor func (sc *SubscriptionClient) WithWebSocket(fn func(sc *SubscriptionClient) (WebsocketConn, error)) *SubscriptionClient ``` ```go // the default websocket constructor func newWebsocketConn(sc *SubscriptionClient) (WebsocketConn, error) { options := &websocket.DialOptions{ Subprotocols: []string{"graphql-ws"}, } c, _, err := websocket.Dial(sc.GetContext(), sc.GetURL(), options) if err != nil { return nil, err } // The default WebsocketHandler implementation using coder's return &WebsocketHandler{ ctx: sc.GetContext(), Conn: c, timeout: sc.GetTimeout(), }, } client := graphql.NewSubscriptionClient("wss://example.com/graphql") defer client.Close() client.WithWebSocket(newWebsocketConn) client.Run() ``` -------------------------------- ### Execute Raw GraphQL Queries in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Provides methods for executing pre-built GraphQL query strings directly, including options to unmarshal into a struct, get raw JSON, or retrieve raw response with extensions. ```go package main import ( "context" "encoding/json" "fmt" "log" "github.com/hasura/go-graphql-client" ) func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) // Execute pre-built query with Exec (unmarshals into struct) query := `query($id: ID!) { user(id: $id) { id, name, email } }` variables := map[string]any{"id": "123"} var result struct { User struct { ID string `json:"id"` Name string `json:"name"` Email string `json:"email"` } `json:"user"` } err := client.Exec(context.Background(), query, &result, variables) if err != nil { log.Fatal(err) } fmt.Printf("User: %s (%s)\n", result.User.Name, result.User.Email) // Execute and get raw JSON response rawQuery := `query { users { id, name } }` rawData, err := client.ExecRaw(context.Background(), rawQuery, nil) if err != nil { log.Fatal(err) } fmt.Println("Raw response:", string(rawData)) // Execute and get raw response with extensions data, extensions, err := client.ExecRawWithExtensions(context.Background(), rawQuery, nil) if err != nil { log.Fatal(err) } fmt.Println("Data:", string(data)) fmt.Println("Extensions:", string(extensions)) // QueryRaw returns raw bytes var q struct { Users []struct { ID string Name string } } rawBytes, err := client.QueryRaw(context.Background(), &q, nil) if err != nil { log.Fatal(err) } fmt.Println("Raw bytes:", string(rawBytes)) } ``` -------------------------------- ### GraphQL Debugging Response Example Source: https://github.com/hasura/go-graphql-client/blob/master/README.md When debug mode is enabled with `WithDebug`, request and response information is included in the `extensions[].internal` property upon request failure. This JSON shows an example error with internal request and response details. ```JSON { "errors": [ { "message": "Field 'user' is missing required arguments: login", "extensions": { "internal": { "request": { "body": "{\"query\":\"{user{name}}\"}", "headers": { "Content-Type": ["application/json"] } }, "response": { "body": "{\"errors\": [{\"message\": \"Field 'user' is missing required arguments: login\",\"locations\": [{\"line\": 7,\"column\": 3}]}]}", "headers": { "Content-Type": ["application/json"] } } } }, "locations": [ { "line": 7, "column": 3 } ] } ] } ``` -------------------------------- ### Configure Connection Initialization Timeout Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Adjust the timeout for connection initialization using `WithConnectionInitialisationTimeout`. Setting the duration to `0` disables the timeout. The `OnError` handler can be used to react to timeout errors, for example, by restarting the client. ```Go client := graphql.NewSubscriptionClient(serverEndpoint). WithConnectionInitialisationTimeout(2*time.Minute). OnError(func(sc *graphql.SubscriptionClient, err error) error { if sc.IsConnectionInitialisationTimeout(err) { // restart the client return nil } // catch other errors... return err }) ``` -------------------------------- ### Define Custom Operation Directive Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Example of defining a custom operation directive, such as `@cached`, for Hasura queries. Implement the `Option` interface to use it. ```go // define @cached directive for Hasura queries // https://hasura.io/docs/latest/graphql/cloud/response-caching.html#enable-caching type cachedDirective struct { ttl int } func (cd cachedDirective) Type() OptionType { // operation_directive return graphql.OptionTypeOperationDirective } func (cd cachedDirective) String() string { if cd.ttl <= 0 { return "@cached" } return fmt.Sprintf("@cached(ttl: %d)", cd.ttl) } ``` -------------------------------- ### Initialize GraphQL Subscription Client Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Construct a subscription client by providing the GraphQL server URL. Ensure to close the client when done and run the client to process subscriptions. ```Go client := graphql.NewSubscriptionClient("wss://example.com/graphql") defer client.Close() // Subscribe subscriptions // ... // finally run the client client.Run() ``` -------------------------------- ### Run Go GraphQL Client Source: https://github.com/hasura/go-graphql-client/blob/master/example/tibber/README.md Execute the Go application after setting the Tibber demo token. ```sh go run . ``` -------------------------------- ### Run Go Client Source: https://github.com/hasura/go-graphql-client/blob/master/example/graphql-ws-bc/README.md Executes the Go GraphQL client application. This command should be run from the root of the project directory. ```bash go run ./client ``` -------------------------------- ### Create a new GraphQL client Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Instantiate a new GraphQL client with the server URL. The second argument can be an http.Client for custom configurations. ```Go client := graphql.NewClient("https://example.com/graphql", nil) // Use client... ``` -------------------------------- ### Create GraphQL Client in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Instantiate a GraphQL client for HTTP queries and mutations. Configure with custom HTTP clients, retry logic, and authentication headers. Debug mode can be enabled for troubleshooting. ```go package main import ( "context" "fmt" "net/http" "time" "github.com/hasura/go-graphql-client" ) func main() { // Basic client creation client := graphql.NewClient("https://api.example.com/graphql", nil) // Client with custom HTTP client and retry options client = graphql.NewClient("https://api.example.com/graphql", http.DefaultClient, graphql.WithRetry(3), graphql.WithRetryBaseDelay(time.Second), graphql.WithRetryExponentialRate(2), graphql.WithRetryHTTPStatus([]int{http.StatusTooManyRequests, http.StatusServiceUnavailable}), ) // Client with authentication header client = graphql.NewClient("https://api.example.com/graphql", http.DefaultClient). WithRequestModifier(func(r *http.Request) { r.Header.Set("Authorization", "Bearer your-token") }) // Enable debug mode client = client.WithDebug(true) fmt.Println("Client created successfully") } ``` -------------------------------- ### Configure Go GraphQL Subscription Client with Auth Source: https://github.com/hasura/go-graphql-client/blob/master/example/graphql-ws-bc/README.md Initializes a new subscription client and configures WebSocket options to include an HTTP Authorization header for authentication. Ensure the server endpoint is correctly specified. ```go client := graphql.NewSubscriptionClient(serverEndpoint). WithWebSocketOptions(graphql.WebsocketOptions{ HTTPHeader: http.Header{ "Authorization": []string{"Bearer random-secret"}, }, }) ``` -------------------------------- ### Execute GraphQL Mutations in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Demonstrates how to define and execute GraphQL mutations with input variables using the go-graphql-client. Ensure your mutation struct and variables are correctly defined. ```go package main import ( "context" "fmt" "log" "github.com/hasura/go-graphql-client" ) type ReviewInput struct { Stars int `json:"stars"` Commentary string `json:"commentary"` } func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) // Define mutation struct // Generates: mutation ($ep: String!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { stars, commentary } } var mutation struct { CreateReview struct { Stars int Commentary string } `graphql:"createReview(episode: $ep, review: $review)"` } variables := map[string]any{ "ep": "JEDI", "review": ReviewInput{ Stars: 5, Commentary: "This is a great movie!", }, } err := client.Mutate(context.Background(), &mutation, variables) if err != nil { log.Fatal(err) } fmt.Printf("Created review with %d stars: %s\n", mutation.CreateReview.Stars, mutation.CreateReview.Commentary) // Output: Created review with 5 stars: This is a great movie! } ``` -------------------------------- ### Create WebSocket Subscription Client in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Initializes a WebSocket client for GraphQL subscriptions. Supports configurable protocols, connection parameters, timeouts, and logging. Use this to set up the connection to your GraphQL endpoint. ```go package main import ( "log" "net/http" "time" "github.com/hasura/go-graphql-client" ) func main() { // Basic subscription client client := graphql.NewSubscriptionClient("wss://api.example.com/graphql") defer client.Close() // Subscription client with full configuration client = graphql.NewSubscriptionClient("wss://api.example.com/graphql"). WithProtocol(graphql.GraphQLWS). // or graphql.SubscriptionsTransportWS (default) WithConnectionParams(map[string]any{ "headers": map[string]string{ "Authorization": "Bearer your-token", }, }). WithTimeout(time.Minute). WithRetryTimeout(time.Minute). WithReadLimit(10 * 1024 * 1024). WithLog(log.Println). WithoutLogTypes(graphql.GQLData, graphql.GQLConnectionKeepAlive). WithExitWhenNoSubscription(true). WithSyncMode(false). WithRetryStatusCodes("4000", "4000-4050"). WithWebSocketOptions(graphql.WebsocketOptions{ HTTPHeader: http.Header{ "Authorization": []string{"Bearer token"}, }, }) // Event handlers client.OnConnected(func() { log.Println("Connected to GraphQL server") }) client.OnDisconnected(func() { log.Println("Disconnected from GraphQL server") }) client.OnConnectionAlive(func() { log.Println("Connection is alive") }) client.OnError(func(sc *graphql.SubscriptionClient, err error) error { log.Printf("Error: %v", err) if sc.IsUnauthorized(err) { return err // Return error to stop client } return nil // Return nil to continue and retry }) // Run the client (blocks until closed) if err := client.Run(); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Configure Subscription Client Options Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Customize the subscription client's behavior with various options, including timeouts, retry logic, logging, message size limits, and operation log filtering. ```Go client. // write timeout of websocket client 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 WithLog(log.Println). // max size of response message WithReadLimit(10*1024*1024). // these operation event logs won't be printed WithoutLogTypes(graphql.GQLData, graphql.GQLConnectionKeepAlive). // 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 WithRetryStatusCodes("4000", "4000-4050"). // WithSyncMode subscription messages are executed in sequence (without goroutine) WithSyncMode(true) ``` -------------------------------- ### Customize Subscription Client HTTP Client Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Configure a custom HTTP client for the subscription client using `WithWebSocketOptions`. This allows for setting timeouts and other HTTP transport configurations. ```go client.WithWebSocketOptions(WebsocketOptions{ HTTPClient: &http.Client{ Transport: http.DefaultTransport, Timeout: time.Minute, } }) ``` -------------------------------- ### Authenticate with Connection Parameters Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Authenticate the subscription client using connection parameters, supporting static headers or dynamically generated parameters via a function. ```Go client := graphql.NewSubscriptionClient("wss://example.com/graphql"). WithConnectionParams(map[string]interface{}{ "headers": map[string]string{ "authentication": "...", }, }). // or lazy parameters with function WithConnectionParamsFn(func () map[string]interface{} { return map[string]interface{} { "headers": map[string]string{ "authentication": "...", }, } }) ``` -------------------------------- ### Query with Operation Name Option Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Demonstrates how to use the built-in `OperationName` option to specify a named query. Ensure the query is defined with the specified name. ```go // query MyQuery { // ... // } client.Query(ctx, &q, variables, graphql.OperationName("MyQuery")) ``` -------------------------------- ### Configure GraphQL Client with Retry Options Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Construct a GraphQL client with options for retrying failed requests, including the number of retries, base delay, exponential rate, and specific HTTP statuses or GraphQL errors to retry on. ```Go client := graphql.NewClient("/graphql", http.DefaultClient, // number of retries graphql.WithRetry(3), // base backoff interval. Optional, default 1 second. // Prioritize the Retry-After header if it exists in the response. graphql.WithRetryBaseDelay(time.Second), // exponential rate. Optional, default 2.0 graphql.WithRetryExponentialRate(2), // retry on http statuses. Optional, default: 429, 502, 503, 504 graphql.WithRetryHTTPStatus([]int{http.StatusServiceUnavailable}), // if the http status is 200 but the graphql response is error, // use this option to check if the error is retryable. graphql.WithRetryOnGraphQLError(func(errs graphql.Errors) bool { return len(errs) == 1 && errs[0].Message == "Field 'user' is missing required arguments: login" }), ) ``` -------------------------------- ### Execute Raw GraphQL Subscriptions in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Allows executing pre-defined subscription queries directly without relying on Go struct reflection. Useful for dynamic or complex queries. Handles raw query strings, variables, and callback functions for received data. ```go package main import ( "log" "github.com/hasura/go-graphql-client" ) func main() { client := graphql.NewSubscriptionClient("wss://api.example.com/graphql") defer client.Close() // Raw subscription query query := `subscription($channelId: ID!) { messageAdded(channelId: $channelId) { id text user { name } } }` variables := map[string]any{ "channelId": "channel-123", } subID, err := client.Exec(query, variables, func(data []byte, err error) error { if err != nil { log.Printf("Error: %v", err) return nil } log.Printf("Received: %s", string(data)) return nil }) if err != nil { log.Fatal(err) } log.Printf("Subscription started with ID: %s", subID) if err := client.Run(); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Subscribe to GraphQL Data in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Establishes a subscription to receive real-time data from a GraphQL endpoint. Handles data parsing and provides callbacks for received data and errors. Supports subscriptions with and without variables. ```go package main import ( "log" "time" "github.com/hasura/go-graphql-client" ) func main() { client := graphql.NewSubscriptionClient("wss://api.example.com/graphql"). WithLog(log.Println) defer client.Close() // Define subscription struct // Generates: subscription { messageAdded { id, text, createdAt } } var subscription struct { MessageAdded struct { ID graphql.ID Text string CreatedAt string } } // Subscribe with handler subID, err := client.Subscribe(&subscription, nil, func(data []byte, err error) error { if err != nil { log.Printf("Subscription error: %v", err) return nil } if data == nil { return nil } // Parse the data using graphql.UnmarshalGraphQL var msg struct { MessageAdded struct { ID graphql.ID Text string CreatedAt string } } if err := graphql.UnmarshalGraphQL(data, &msg); err != nil { log.Printf("Unmarshal error: %v", err) return nil } log.Printf("New message: %s - %s", msg.MessageAdded.ID, msg.MessageAdded.Text) return nil }) if err != nil { log.Fatal(err) } // Subscribe with variables var subWithVars struct { MessageAdded struct { ID graphql.ID Text string } `graphql:"messageAdded(channelId: $channelId)"` } variables := map[string]any{ "channelId": graphql.ID("channel-123"), } subID2, err := client.Subscribe(&subWithVars, variables, func(data []byte, err error) error { log.Println("Received:", string(data)) return nil }, graphql.OperationName("WatchMessages")) if err != nil { log.Fatal(err) } // Unsubscribe after some time go func() { time.Sleep(30 * time.Second) client.Unsubscribe(subID) client.Unsubscribe(subID2) }() // Run blocks until all subscriptions are closed or client.Close() is called if err := client.Run(); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Construct GraphQL Queries, Mutations, and Subscriptions Source: https://context7.com/hasura/go-graphql-client/llms.txt Uses construction functions to generate GraphQL query, mutation, and subscription strings without executing them. This is useful for debugging and unit testing. Ensure all necessary types are imported. ```go package main import ( "fmt" "log" "github.com/hasura/go-graphql-client" ) func main() { // Construct a query string var query struct { User struct { ID string Name string Email string } `graphql:"user(id: $id)"` } variables := map[string]any{ "id": graphql.ID("123"), } queryString, err := graphql.ConstructQuery(&query, variables, graphql.OperationName("GetUser")) if err != nil { log.Fatal(err) } fmt.Println("Query:", queryString) // Output: Query: query GetUser($id:ID!){user(id: $id){id,name,email}} // Construct a mutation string var mutation struct { CreateUser struct { ID string } `graphql:"createUser(name: $name)"` } mutationVars := map[string]any{ "name": "John", } mutationString, err := graphql.ConstructMutation(&mutation, mutationVars) if err != nil { log.Fatal(err) } fmt.Println("Mutation:", mutationString) // Output: Mutation: mutation ($name:String!){createUser(name: $name){id}} // Construct a subscription string var subscription struct { MessageAdded struct { ID string Text string } } subString, opName, err := graphql.ConstructSubscription(&subscription, nil, graphql.OperationName("WatchMessages")) if err != nil { log.Fatal(err) } fmt.Println("Subscription:", subString) fmt.Println("Operation Name:", opName) // Output: Subscription: subscription WatchMessages{messageAdded{id,text}} // Output: Operation Name: WatchMessages } ``` -------------------------------- ### Execute a Simple GraphQL Query Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Define a Go struct that mirrors the expected GraphQL response structure and use client.Query to fetch data. Ensure variable names in the struct are uppercase. ```Go var query struct { Me struct { Name string } } err := client.Query(context.Background(), &query, nil) if err != nil { // Handle error. } fmt.Println(query.Me.Name) // Output: Luke Skywalker ``` -------------------------------- ### GraphQL Query Construction Functions in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Use these `Construct*` functions to inspect the generated GraphQL query string. This is useful for debugging and writing unit tests to ensure query correctness, as queries are generated at runtime using reflection. ```Go // ConstructQuery build GraphQL query string from struct and variables func ConstructQuery(v interface{}, variables map[string]interface{}, options ...Option) (string, error) ``` ```Go // ConstructMutation build GraphQL mutation string from struct and variables func ConstructMutation(v interface{}, variables map[string]interface{}, options ...Option) (string, error) ``` ```Go // ConstructSubscription build GraphQL subscription string from struct and variables func ConstructSubscription(v interface{}, variables map[string]interface{}, options ...Option) (string, string, error) ``` ```Go // 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 ``` -------------------------------- ### Prepare and Execute GraphQL Query with Variables in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Define a `variables` map containing the values for your query variables. Pass this map to `client.Query` to execute the query with dynamic arguments. ```Go variables := map[string]interface{}{ "id": graphql.ID(id), "unit": starwars.LengthUnit("METER"), } err := client.Query(context.Background(), &q, variables) if err != nil { // Handle error. } ``` -------------------------------- ### Set Subscription Protocol Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Switch the subscription client's protocol between the default `subscriptions-transport-ws` and `graphql-ws` using the `WithProtocol` function. ```Go client.WithProtocol(graphql.GraphQLWS) ``` -------------------------------- ### Execute Simple GraphQL Query in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Perform a basic GraphQL query by defining a Go struct that matches the expected response structure. Field names in the struct are automatically mapped to camelCase for the GraphQL query. ```go package main import ( "context" "fmt" "log" "github.com/hasura/go-graphql-client" ) func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) // Define query struct - generates: { viewer { login, name, createdAt } } var query struct { Viewer struct { Login string Name string CreatedAt string } } err := client.Query(context.Background(), &query, nil) if err != nil { log.Fatal(err) } fmt.Printf("User: %s (%s)\n", query.Viewer.Name, query.Viewer.Login) // Output: User: John Doe (johndoe) } ``` -------------------------------- ### GraphQL Subscription with Callback in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Define a Go type for the subscription response, call client.Subscribe with the query, variables, and a callback function to handle received data or errors. Use jsonutil.UnmarshalGraphQL for unmarshalling. ```GraphQL subscription { me { name } } ``` ```Go var subscription struct { Me struct { Name string } } ``` ```Go subscriptionId, err := client.Subscribe(&query, nil, func(dataValue []byte, errValue error) error { if errValue != nil { // handle error // if returns error, it will failback to `onError` event return nil } data := query{} // use the github.com/hasura/go-graphql-client/pkg/jsonutil package err := jsonutil.UnmarshalGraphQL(dataValue, &data) fmt.Println(query.Me.Name) // Output: Luke Skywalker return nil }) if err != nil { // Handle error. } ``` -------------------------------- ### GraphQL Queries with Arguments and Variables in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Execute GraphQL queries that require arguments using struct tags or pass variables using a map. The library handles the generation of typed GraphQL queries with variables. ```go package main import ( "context" "fmt" "log" "github.com/hasura/go-graphql-client" ) func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) // Query with inline arguments // Generates: { human(id: "1000") { name, height(unit: METER) } } var q struct { Human struct { Name string Height float64 `graphql:"height(unit: METER)"` } `graphql:"human(id: \"1000\")"` } err := client.Query(context.Background(), &q, nil) if err != nil { log.Fatal(err) } // Query with variables // Generates: query ($id: ID!, $unit: LengthUnit!) { human(id: $id) { name, height(unit: $unit) } } var query struct { Human struct { Name string Height float64 `graphql:"height(unit: $unit)"` } `graphql:"human(id: $id)"` } variables := map[string]any{ "id": graphql.ID("1000"), "unit": "METER", } err = client.Query(context.Background(), &query, variables) if err != nil { log.Fatal(err) } fmt.Printf("%s: %.2f meters\n", query.Human.Name, query.Human.Height) // Output: Luke Skywalker: 1.72 meters } ``` -------------------------------- ### Set Tibber Demo Token Source: https://github.com/hasura/go-graphql-client/blob/master/example/tibber/README.md Export your Tibber demo token as an environment variable before running the application. ```sh export TIBBER_DEMO_TOKEN= ``` -------------------------------- ### Execute Query with Inline Fragments in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Execute a query that includes inline fragments using `client.Query`. The results for the specific fragment types will be populated in the corresponding struct fields. ```Go err := client.Query(context.Background(), &q, nil) if err != nil { // Handle error. } fmt.Println(q.Hero.Name) fmt.Println(q.Hero.PrimaryFunction) fmt.Println(q.Hero.Height) ``` -------------------------------- ### Authenticate with HTTP Headers Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Authenticate the subscription client using HTTP headers, particularly useful when servers validate custom authentication tokens. ```Go client := graphql.NewSubscriptionClient(serverEndpoint). WithWebSocketOptions(graphql.WebsocketOptions{ HTTPHeader: http.Header{ "Authorization": []string{"Bearer random-secret"}, }, }) ``` -------------------------------- ### Subscription Client Event Handlers Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Register callback functions for various WebSocket connection events. These events include successful connection, disconnection, general errors, keep-alive messages, and subscription completion. ```go // OnConnected event is triggered when the websocket connected to GraphQL server sucessfully client.OnConnected(fn func()) ``` ```go // OnDisconnected event is triggered when the websocket client was disconnected client.OnDisconnected(fn func()) ``` ```go // OnError event is triggered when there is any connection error. This is bottom exception handler level // If this function is empty, or returns nil, the error is ignored // If returns error, the websocket connection will be terminated client.OnError(onError func(sc *SubscriptionClient, err error) error) ``` ```go // OnConnectionAlive event is triggered when the websocket receive a connection alive message (differs per protocol) client.OnConnectionAlive(fn func()) ``` ```go // OnSubscriptionComplete event is triggered when the subscription receives a terminated message from the server client.OnSubscriptionComplete(fn func(sub Subscription)) ``` -------------------------------- ### Use Operation Names and Custom Directives in Go Source: https://context7.com/hasura/go-graphql-client/llms.txt Shows how to add operation names for debugging and apply custom directives like caching to GraphQL queries. You can also bind response headers and extensions. ```go package main import ( "context" "fmt" "log" "net/http" "github.com/hasura/go-graphql-client" ) // Custom directive for Hasura caching type cachedDirective struct { ttl int } func (cd cachedDirective) Type() graphql.OptionType { return graphql.OptionTypeOperationDirective } func (cd cachedDirective) String() string { if cd.ttl <= 0 { return "@cached" } return fmt.Sprintf("@cached(ttl: %d)", cd.ttl) } func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) var query struct { User struct { ID string Name string } } // Query with operation name // Generates: query GetUser { user { id, name } } err := client.Query(context.Background(), &query, nil, graphql.OperationName("GetUser")) if err != nil { log.Fatal(err) } // Query with operation name and custom directive // Generates: query GetUser @cached(ttl: 60) { user { id, name } } err = client.Query(context.Background(), &query, nil, graphql.OperationName("GetUser"), cachedDirective{ttl: 60}, ) if err != nil { log.Fatal(err) } // Bind response headers headers := http.Header{} err = client.Query(context.Background(), &query, nil, graphql.BindResponseHeaders(&headers)) if err != nil { log.Fatal(err) } fmt.Println("Content-Type:", headers.Get("Content-Type")) // Bind extensions from response var extensions struct { RequestID string `json:"requestId"` } err = client.Query(context.Background(), &query, nil, graphql.BindExtensions(&extensions)) if err != nil { log.Fatal(err) } fmt.Println("Request ID:", extensions.RequestID) } ``` -------------------------------- ### Authenticate GraphQL Client with OAuth2 Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Integrate with golang.org/x/oauth2 to authenticate your GraphQL client using an OAuth2 token. This requires setting up an oauth2.TokenSource. ```Go import "golang.org/x/oauth2" func main() { src := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: os.Getenv("GRAPHQL_TOKEN")}, ) httpClient := oauth2.NewClient(context.Background(), src) client := graphql.NewClient("https://example.com/graphql", httpClient) // Use client... } ``` -------------------------------- ### GraphQL Mutation with Fields in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Define a Go struct to match the mutation response fields and use a map for variables. Call client.Mutate to execute the mutation. ```GraphQL mutation($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) { stars commentary } } variables { "ep": "JEDI", "review": { "stars": 5, "commentary": "This is a great movie!" } } ``` ```Go var m struct { CreateReview struct { Stars int Commentary string } `graphql:"createReview(episode: $ep, review: $review)"` } variables := map[string]interface{}{ "ep": starwars.Episode("JEDI"), "review": starwars.ReviewInput{ Stars: 5, Commentary: "This is a great movie!", }, } ``` ```Go err := client.Mutate(context.Background(), &m, variables) if err != nil { // Handle error. } fmt.Printf("Created a %v star review: %v\n", m.CreateReview.Stars, m.CreateReview.Commentary) ``` ```text // Output: // Created a 5 star review: This is a great movie! ``` -------------------------------- ### Implement Custom GraphQL Types Source: https://context7.com/hasura/go-graphql-client/llms.txt Implements custom GraphQL type names using the GraphQLType interface, useful for lowercase type names or custom scalar types. Also demonstrates using the `scalar` tag to prevent field expansion and `graphql:"-"` to skip fields. ```go package main import ( "context" "fmt" "log" "github.com/hasura/go-graphql-client" ) // Custom input type with lowercase GraphQL name type UserReviewInput struct { Review string `json:"review"` UserID string `json:"userId"` } // Implement GraphQLType interface func (u UserReviewInput) GetGraphQLType() string { return "user_review_input" } // Custom scalar type - mark with scalar:"true" to prevent field expansion type JSONObject map[string]any func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) // Using custom GraphQL type // Generates: mutation ($input: user_review_input!) { submitReview(input: $input) { id } } var mutation struct { SubmitReview struct { ID string } `graphql:"submitReview(input: $input)"` } variables := map[string]any{ "input": UserReviewInput{ Review: "Great product!", UserID: "user-123", }, } err := client.Mutate(context.Background(), &mutation, variables) if err != nil { log.Fatal(err) } fmt.Printf("Review ID: %s\n", mutation.SubmitReview.ID) // Using scalar tag to prevent field expansion var queryWithScalar struct { Config struct { Settings JSONObject `scalar:"true"` } } // This generates: { config { settings } } instead of expanding settings fields err = client.Query(context.Background(), &queryWithScalar, nil) if err != nil { log.Fatal(err) } // Skip fields with graphql:"-" var querySkip struct { User struct { ID string `graphql:"-"` // Skipped Name string CreatedAt string `graphql:"-"` // Skipped } } // Generates: { user { name } } err = client.Query(context.Background(), &querySkip, nil) if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Execute Multiple Mutations with Ordered Map Source: https://context7.com/hasura/go-graphql-client/llms.txt Executes multiple mutations in a single request using ordered map syntax. This is useful when struct definitions are impractical or for complex mutation ordering. ```go package main import ( "context" "fmt" "log" "github.com/hasura/go-graphql-client" ) type CreateUser struct { Login string } func main() { client := graphql.NewClient("https://api.example.com/graphql", nil) // Multiple mutations using ordered map // Generates: mutation ($login1: String!, $login2: String!, $login3: String!) { // user1: createUser(login: $login1) { login } // user2: createUser(login: $login2) { login } // user3: createUser(login: $login3) { login } // } mutations := [][2]any{ {"user1: createUser(login: $login1)", &CreateUser{}}, {"user2: createUser(login: $login2)", &CreateUser{}}, {"user3: createUser(login: $login3)", &CreateUser{}}, } variables := map[string]any{ "login1": "alice", "login2": "bob", "login3": "charlie", } err := client.Mutate(context.Background(), &mutations, variables) if err != nil { log.Fatal(err) } for _, m := range mutations { user := m[1].(*CreateUser) fmt.Printf("Created user: %s\n", user.Login) } } ``` -------------------------------- ### Define GraphQL Option Interface Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Defines the interface for optional arguments in GraphQL queries. Use this to create custom options. ```go type Option interface { Type() OptionType String() string } ``` -------------------------------- ### Query with Custom Operation Directive Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Shows how to include a custom operation directive, like the `cachedDirective`, when executing a query. This allows server-side caching. ```go // query MyQuery @cached { // ... // } client.Query(ctx, &q, variables, graphql.OperationName("MyQuery"), cachedDirective{}) ``` -------------------------------- ### Deprecated Named Query and Mutate Functions Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Provides function signatures for deprecated methods `NamedQuery`, `NamedMutate`, and `NamedSubscribe`. These are for reference and should be replaced with current API usage. ```go func (c *Client) NamedQuery(ctx context.Context, name string, q interface{}, variables map[string]interface{}) error ``` ```go func (c *Client) NamedMutate(ctx context.Context, name string, q interface{}, variables map[string]interface{}) error ``` ```go func (sc *SubscriptionClient) NamedSubscribe(name string, v interface{}, variables map[string]interface{}, handler func(message []byte, err error) error) (string, error) ``` -------------------------------- ### Execute GraphQL Query with Constant Arguments in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md After defining the query struct with constant arguments, execute the query using `client.Query`. Ensure to handle potential errors and access the results. ```Go err := client.Query(context.Background(), &q, nil) if err != nil { // Handle error. } fmt.Println(q.Human.Name) fmt.Println(q.Human.Height) ``` -------------------------------- ### Execute Dynamically Built Subscription Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Executes a GraphQL subscription with a dynamically constructed `where` clause. Handles incoming messages via a callback function. ```go subscription := "subscription{something(where: {" + strings.Join(filters, ", ") + "}){id}}" subscriptionId, err := subscriptionClient.Exec(subscription, nil, func(dataValue []byte, 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) // ... }) ``` -------------------------------- ### Define Custom WebSocket Connection Interface Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Define the `WebsocketConn` interface to abstract WebSocket connection operations like reading/writing JSON, closing the connection, and setting read limits. This allows for using alternative WebSocket implementations. ```go // WebsocketHandler abstracts WebSocket connection functions // ReadJSON and WriteJSON data of a frame from the WebSocket connection. // Close the WebSocket connection. type WebsocketConn interface { ReadJSON(v interface{}) error WriteJSON(v interface{}) error Close() error // SetReadLimit sets the maximum size in bytes for a message read from the peer. If a // message exceeds the limit, the connection sends a close message to the peer // and returns ErrReadLimit to the application. SetReadLimit(limit int64) } ``` -------------------------------- ### Define GraphQL Query with Variable Arguments in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md When arguments are not known in advance, use variable names in the `graphql` struct field tag (e.g., `$id`, `$unit`). This allows for dynamic query construction. ```Go var q struct { Human struct { Name string Height float64 `graphql:"height(unit: $unit)"` } `graphql:"human(id: $id)"` } ``` -------------------------------- ### GraphQL Mutation Without Fields in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Define a Go struct with a string field for mutations that do not return any specific fields. Call client.Mutate to execute. ```GraphQL mutation($ep: Episode!, $review: ReviewInput!) { createReview(episode: $ep, review: $review) } variables { "ep": "JEDI", "review": { "stars": 5, "commentary": "This is a great movie!" } } ``` ```Go var m struct { CreateReview string `graphql:"createReview(episode: $ep, review: $review)"` } variables := map[string]interface{}{ "ep": starwars.Episode("JEDI"), "review": starwars.ReviewInput{ Stars: 5, Commentary: "This is a great movie!", }, } ``` ```Go err := client.Mutate(context.Background(), &m, variables) if err != nil { // Handle error. } fmt.Printf("Created a review: %s.\n", m.CreateReview) ``` ```text // Output: // Created a review: . ``` -------------------------------- ### Bind Response Headers Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Binds HTTP headers from the GraphQL response into a provided `http.Header` map. Useful for inspecting response metadata. ```go headers := http.Header{} err := client.Query(context.TODO(), &q, map[string]any{}, graphql.BindResponseHeaders(&headers)) if err != nil { panic(err) } fmt.Println(headers.Get("content-type")) // application/json ``` -------------------------------- ### Bind Extensions from Response Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Binds extension data from the GraphQL response into a provided struct. The client attempts to unmarshal the 'extensions' field. ```go var q struct { User struct { ID string `graphql:"id"` Name string `graphql:"name"` } } var ext struct { ID int `json:"id"` Domain string `json:"domain"` } err := client.Query(context.Background(), &q, map[string]interface{}{}, graphql.BindExtensions(&ext)) if err != nil { t.Fatal(err) } ``` -------------------------------- ### Define GraphQL Query with Constant Arguments in Go Source: https://github.com/hasura/go-graphql-client/blob/master/README.md Use the `graphql` struct field tag to specify constant arguments for fields in your GraphQL queries. This is suitable when arguments are known at compile time. ```Go var q struct { Human struct { Name string Height float64 `graphql:"height(unit: METER)"` } `graphql:"human(id: \"1000\")"` } ```