octoql

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: MIT Imports: 13 Imported by: 0

README

Go Reference Test Status Contributor Covenant

octoql

octoql generates type-safe Go clients and typed test handlers for GitHub-shaped GraphQL APIs. It validates queries and mutations against a pinned schema, then generates Go types and helpers backed by a small root runtime package.

octoql is a standalone project derived from Khan/genqlient. See THIRD_PARTY_NOTICES.md for exact source pins and attribution.

Requirements and installation

octoql requires Go 1.26 or newer. Add the runtime and pin octoqlgen as a Go tool dependency in the module that owns the generated client:

go get github.com/willabides/octoql
go get -tool github.com/willabides/octoql/cmd/octoqlgen

Run the pinned tool with go tool octoqlgen. The Go tool dependency is the recommended installation because the runtime and generator then resolve from the same module version.

For a standalone binary, install a release archive with bindown:

bindown template-source add octoql https://github.com/WillAbides/octoql/releases/latest/download/bindown.yaml
bindown dependency add octoqlgen --source octoql

Or build a standalone binary from source with an explicit version or commit:

go install github.com/willabides/octoql/cmd/octoqlgen@<version-or-commit>

Generate a client

Initialize a project:

go tool octoqlgen init

GitHub authentication must be available through GH_TOKEN, GITHUB_TOKEN, or the gh CLI.

This resolves and fetches the latest GitHub Docs Free, Pro, & Team (fpt) schema, then creates a configuration containing its commit revision and SHA-256 digest. It also creates .octoql/.gitignore; the generated config uses the gitignored .octoql/schema.graphql path, graphql/**/*.graphql for operations, and internal/githubapi/generated.go for output.

Choose another GitHub Docs schema version with --schema-version:

go tool octoqlgen init --schema-version ghec
go tool octoqlgen init --schema-version ghes-3.21

Add the JSON Schema directive to the generated octoqlgen.yaml for editor completion and validation. The initialized schema configuration has this form:

# yaml-language-server: $schema=https://raw.githubusercontent.com/WillAbides/octoql/main/octoqlgen.schema.yaml

schema:
  path: .octoql/schema.graphql
  sha256: c98cb9edeedd1fb56c8678c19a8ad540c8d0739dd94579dfedbe044192e4ab18
  source:
    repository: github/docs
    path: src/graphql/data/fpt/schema.docs.graphql
    revision: 45d83f459620340069df7c375a8867be62616d61
operations:
  - graphql/**/*.graphql
generated: internal/githubapi/generated.go

Repository checkouts can use # yaml-language-server: $schema=./octoqlgen.schema.yaml instead. All paths and globs are relative to octoqlgen.yaml. See docs/octoqlgen.yaml for local schemas, other remote sources, and every configuration option.

Create graphql/repository.graphql:

query GetRepository($owner: String!, $name: String!, $first: Int!) {
  repository(owner: $owner, name: $name) {
    nameWithOwner
    issues(first: $first) {
      nodes {
        number
        title
      }
    }
  }
}

Fetch or verify the configured schema, then generate:

go tool octoqlgen schema fetch
go tool octoqlgen generate

Generation performs the same schema verification or fetch before it writes code. Query and mutation operation names become generated helper names, so use an uppercase name when the helper must be exported. octoql does not support GraphQL subscriptions, and octoqlgen rejects subscription operations.

Operations may also be embedded in Go string literals. See the directive reference for embedded operations and per-operation options.

Schema sources and updates

schema.path is always the schema used for generation. Keep it in the gitignored .octoql directory when the source is remote. A local schema needs only its path:

schema:
  path: schema/github.graphql

GitHub.com sources require a SHA-256 digest and full commit SHA. Authentication uses GH_TOKEN, GITHUB_TOKEN, or gh auth token. See the configuration reference for all schema settings.

octoqlgen init configures and fetches the latest fpt schema by default. Pass --schema-version to initialize with another GitHub Docs version.

schema fetch verifies an existing file or fetches a missing remote file:

go tool octoqlgen schema fetch

schema update fetches the latest version of the configured repository path from its default branch, validates and writes it, then updates the configuration revision and sha256. Run schema updates serially.

go tool octoqlgen schema update
git diff -- octoqlgen.yaml
go tool octoqlgen generate

The .octoql schema normally remains ignored while the reviewed pin in octoqlgen.yaml is committed. Use --config PATH with fetch, update, or generate when the config has another name or location.

Call the generated client

Configure GitHub bearer authentication directly on the client:

client := octoql.NewClient("https://api.github.com/graphql", nil)
err := client.SetBearerToken(os.Getenv("GITHUB_TOKEN"))
if err != nil {
	return err
}

response, err := githubapi.GetRepository(
	ctx,
	client,
	githubapi.GetRepositoryVariables{
		Owner: "octo-org",
		Name:  "octo-repo",
		First: 10,
	},
)
if err != nil {
	return err
}
fmt.Println(response.Repository.NameWithOwner)

Pass a different endpoint to octoql.NewClient for GHES, a proxy, or an httptest.Server. Pass nil as the HTTP client to use http.DefaultClient.

For basic authentication or another authentication scheme, configure the http.Client or http.RoundTripper passed to NewClient.

Runtime responses and errors

Generated helpers return a pointer to the concrete operation response and an error. The response is nil when the error is non-nil. Sometimes GitHub returns partial data with an error. Use errors.AsType to check for partial data:

partialErr, ok := errors.AsType[*githubapi.GetRepositoryPartialDataError](err)
if ok {
	fmt.Printf("partial repository: %+v\n", partialErr.PartialData().Repository)
}

Every failure after receiving an HTTP response includes *octoql.ResponseError. GraphQL errors, rate limits, and partial data are independent error facets, so use errors.AsType for each detail your application needs. The client never retries automatically. See the root runtime API for error and rate-limit details.

Generated types and GitHub defaults

GraphQL's built-in scalars map to ordinary Go values:

GraphQL Go
Int int
Float float64
String, ID string
Boolean bool

Nullable named values generate as pointers by default. Use @octoqlgen(pointer: false) on an argument or selected field when its zero value should represent GraphQL null. octoqlgen includes bindings for common GitHub scalars; add a binding for unknown custom scalars. See the configuration reference and directive reference for scalar bindings, abstract types, and field options.

Typed test handlers

Generate a typed http.Handler from the configured operations:

generated: internal/githubapi/generated.go
test_handler:
  generated: internal/githubapitest/generated.go
  types: client

types: client is the default and makes handler response values assignable to generated client types.

Use types: local to generate separate handler types:

test_handler:
  generated: internal/githubapitest/generated.go
  types: local

Local handler values are not assignable to client types. Test-handler configuration requires query and mutation names to begin with an uppercase letter.

After go tool octoqlgen generate, each handler operation has matching Expect<Operation>, Default<Operation>, and Reset<Operation> methods:

handler := githubapitest.NewTestHandler(t)
server := httptest.NewServer(handler)
t.Cleanup(server.Close)

variables := githubapitest.GetRepositoryVariables{
	Owner: "octo-org",
	Name:  "octo-repo",
	First: 1,
}
handler.ExpectGetRepository(variables, githubapitest.Times(2)).
	Respond(githubapitest.GetRepositoryResponse{
		Repository: githubapitest.GetRepositoryRepository{
			NameWithOwner: "octo-org/octo-repo",
		},
	})

client := octoql.NewClient(server.URL, server.Client())
response, err := githubapi.GetRepository(
	t.Context(),
	client,
	variables,
)
require.NoError(t, err)
require.Equal(t, "octo-org/octo-repo", response.Repository.NameWithOwner)

An expectation defaults to one call. Pass Times(n) to require exactly n, MinTimes(n) to set a minimum, or MinTimes(0) to create an unlimited stub. Default<Operation> is an unlimited fallback. Cleanup verifies unmet expectations, and expectation state is safe for concurrent requests.

Expectations can also configure partial data, errors, headers, status, and rate limits.

Reference

Documentation

Overview

Package octoql provides reusable runtime APIs for generated GraphQL clients.

Index

Examples

Constants

View Source
const DefaultResponseSizeLimit int64 = 10 * 1024 * 1024

DefaultResponseSizeLimit is the maximum GraphQL HTTP response body size a Client accepts for decoding unless configured otherwise. It is 10 MiB.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client executes GraphQL operations against an HTTP endpoint.

Configure bearer authentication with Client.SetBearerToken. Other request behavior, including other authentication schemes, belongs on the supplied http.Client or its http.RoundTripper. A Client may be used concurrently after construction.

func NewClient

func NewClient(endpoint string, httpClient *http.Client) *Client

NewClient returns a client for endpoint. A nil httpClient uses http.DefaultClient.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"

	"github.com/willabides/octoql"
)

type exampleViewerResponse struct {
	Viewer struct {
		Login string `json:"login"`
	} `json:"viewer"`
}

type exampleViewerPartialDataError struct {
	data *exampleViewerResponse
	err  error
}

func (e *exampleViewerPartialDataError) Error() string { return e.err.Error() }
func (e *exampleViewerPartialDataError) Unwrap() error { return e.err }
func (e *exampleViewerPartialDataError) PartialData() *exampleViewerResponse {
	return e.data
}

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
		writer.Header().Set("Content-Type", "application/json")
		_, err := io.WriteString(writer, `{"data":{"viewer":{"login":"octocat"}}}`)
		if err != nil {
			panic(err)
		}
	}))
	defer server.Close()

	client := octoql.NewClient(server.URL, server.Client())
	response, err := getViewer(context.Background(), client)
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(response.Viewer.Login)
}

func getViewer(
	ctx context.Context,
	client *octoql.Client,
) (*exampleViewerResponse, error) {
	return executeExample[exampleViewerResponse](
		ctx,
		client,
		"Viewer",
		"query Viewer { viewer { login } }",
		func(data *exampleViewerResponse, err error) error {
			return &exampleViewerPartialDataError{data: data, err: err}
		},
	)
}

func executeExample[T any](
	ctx context.Context,
	client *octoql.Client,
	operationName string,
	query string,
	newPartialDataError func(*T, error) error,
) (*T, error) {
	response := new(T)
	hasData, err := client.Execute(ctx, octoql.Payload{
		OperationName: operationName,
		Query:         query,
	}, response)
	if !hasData {
		return nil, err
	}
	if err != nil {
		return nil, newPartialDataError(response, err)
	}
	return response, nil
}
Output:
octocat

func (*Client) Execute

func (c *Client) Execute(ctx context.Context, payload Payload, response any) (bool, error)

Execute runs operation and decodes its response data into response.

Execute is a generated-code contract. Response must be a non-nil pointer. The returned boolean reports whether the GraphQL data field decoded successfully and response is usable, including when GraphQL errors are also returned. Every failure after the server returns an HTTP response includes ResponseError. GraphQL errors and rate limits remain discoverable in that error chain as Errors and RateLimitError.

func (*Client) RateLimit

func (c *Client) RateLimit() (RateLimit, bool)

RateLimit returns the latest valid primary rate-limit snapshot observed by client. The boolean is false until a response includes a valid X-RateLimit-Remaining header.

The snapshot is advisory: other clients and processes can consume the same GitHub rate-limit budget after it is observed.

Example
package main

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"

	"github.com/willabides/octoql"
)

type exampleViewerResponse struct {
	Viewer struct {
		Login string `json:"login"`
	} `json:"viewer"`
}

type exampleViewerPartialDataError struct {
	data *exampleViewerResponse
	err  error
}

func (e *exampleViewerPartialDataError) Error() string { return e.err.Error() }
func (e *exampleViewerPartialDataError) Unwrap() error { return e.err }
func (e *exampleViewerPartialDataError) PartialData() *exampleViewerResponse {
	return e.data
}

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
		writer.Header().Set("X-RateLimit-Limit", "5000")
		writer.Header().Set("X-RateLimit-Remaining", "4999")
		writer.Header().Set("X-RateLimit-Used", "1")
		_, err := io.WriteString(writer, `{"data":{}}`)
		if err != nil {
			panic(err)
		}
	}))
	defer server.Close()

	client := octoql.NewClient(server.URL, server.Client())
	_, err := getViewer(context.Background(), client)
	if err != nil {
		fmt.Println(err)
		return
	}

	rateLimit, known := client.RateLimit()
	fmt.Println(known)
	fmt.Println(rateLimit.Limit)
	fmt.Println(rateLimit.Remaining)
}

func getViewer(
	ctx context.Context,
	client *octoql.Client,
) (*exampleViewerResponse, error) {
	return executeExample[exampleViewerResponse](
		ctx,
		client,
		"Viewer",
		"query Viewer { viewer { login } }",
		func(data *exampleViewerResponse, err error) error {
			return &exampleViewerPartialDataError{data: data, err: err}
		},
	)
}

func executeExample[T any](
	ctx context.Context,
	client *octoql.Client,
	operationName string,
	query string,
	newPartialDataError func(*T, error) error,
) (*T, error) {
	response := new(T)
	hasData, err := client.Execute(ctx, octoql.Payload{
		OperationName: operationName,
		Query:         query,
	}, response)
	if !hasData {
		return nil, err
	}
	if err != nil {
		return nil, newPartialDataError(response, err)
	}
	return response, nil
}
Output:
true
5000
4999

func (*Client) ResponseSizeLimit

func (c *Client) ResponseSizeLimit() int64

ResponseSizeLimit returns the maximum HTTP response body size Client accepts for decoding. A newly constructed Client uses DefaultResponseSizeLimit.

func (*Client) SetBearerToken

func (c *Client) SetBearerToken(token string) error

SetBearerToken configures the OAuth 2.0 bearer token sent with each request. token must use the RFC 6750 b64token syntax. It may be called concurrently with Client.Execute to rotate credentials.

func (*Client) SetResponseSizeLimit

func (c *Client) SetResponseSizeLimit(limit int64) error

SetResponseSizeLimit configures the maximum HTTP response body size Client accepts for decoding. limit must be greater than zero. It may be called concurrently with Client.Execute.

type Error

type Error struct {
	Type       ErrorType      `json:"type,omitempty"`
	Message    string         `json:"message"`
	Path       Path           `json:"path,omitempty"`
	Locations  []Location     `json:"locations,omitempty"`
	Extensions map[string]any `json:"extensions,omitempty"`
}

Error describes an error returned in a GraphQL response.

func (*Error) Error

func (e *Error) Error() string

Error returns the GraphQL error message and response path.

type ErrorType

type ErrorType string

ErrorType identifies a GitHub GraphQL error category. It is an open string type so values introduced by GitHub remain available to callers.

type Errors

type Errors []*Error

Errors is the list of errors returned in a GraphQL response.

Example (PartialData)
package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"

	"github.com/willabides/octoql"
)

type exampleRepositoryResponse struct {
	Repository struct {
		Name string `json:"name"`
	} `json:"repository"`
}

type exampleRepositoryPartialDataError struct {
	data *exampleRepositoryResponse
	err  error
}

func (e *exampleRepositoryPartialDataError) Error() string { return e.err.Error() }
func (e *exampleRepositoryPartialDataError) Unwrap() error { return e.err }
func (e *exampleRepositoryPartialDataError) PartialData() *exampleRepositoryResponse {
	return e.data
}

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
		writer.Header().Set("Content-Type", "application/json")
		_, err := io.WriteString(writer, `{
			"data":{"repository":{"name":"octoql"}},
			"errors":[{"type":"FORBIDDEN","message":"owner unavailable","path":["repository","owner"]}]
		}`)
		if err != nil {
			panic(err)
		}
	}))
	defer server.Close()

	client := octoql.NewClient(server.URL, server.Client())
	response, err := getRepository(context.Background(), client)

	var graphqlErrors octoql.Errors
	if errors.As(err, &graphqlErrors) {
		fmt.Println(response == nil)
		partialErr, ok := errors.AsType[*exampleRepositoryPartialDataError](err)
		if ok {
			fmt.Println(partialErr.PartialData().Repository.Name)
		}
		fmt.Println(graphqlErrors[0].Type)
	}
}

func getRepository(
	ctx context.Context,
	client *octoql.Client,
) (*exampleRepositoryResponse, error) {
	return executeExample[exampleRepositoryResponse](
		ctx,
		client,
		"Repository",
		"query Repository { repository { name owner { login } } }",
		func(data *exampleRepositoryResponse, err error) error {
			return &exampleRepositoryPartialDataError{data: data, err: err}
		},
	)
}

func executeExample[T any](
	ctx context.Context,
	client *octoql.Client,
	operationName string,
	query string,
	newPartialDataError func(*T, error) error,
) (*T, error) {
	response := new(T)
	hasData, err := client.Execute(ctx, octoql.Payload{
		OperationName: operationName,
		Query:         query,
	}, response)
	if !hasData {
		return nil, err
	}
	if err != nil {
		return nil, newPartialDataError(response, err)
	}
	return response, nil
}
Output:
true
octoql
FORBIDDEN

func (Errors) Error

func (e Errors) Error() string

Error returns a stable summary of all GraphQL errors.

func (Errors) Unwrap

func (e Errors) Unwrap() []error

Unwrap exposes individual GraphQL errors to errors.Is, errors.As, and errors.AsType.

type Location

type Location struct {
	Line   int `json:"line,omitempty"`
	Column int `json:"column,omitempty"`
}

Location identifies a line and column in a GraphQL document.

type NoMarshalJSON

type NoMarshalJSON struct{}

NoMarshalJSON is for generated code only.

Embedding NoMarshalJSON alongside a type with a MarshalJSON method prevents that sibling method from being promoted.

func (NoMarshalJSON) MarshalJSON

func (NoMarshalJSON) MarshalJSON() ([]byte, error)

MarshalJSON should never be called. It exists only to prevent a sibling MarshalJSON method from being promoted.

type NoUnmarshalJSON

type NoUnmarshalJSON struct{}

NoUnmarshalJSON is for generated code only.

Embedding NoUnmarshalJSON alongside a type with an UnmarshalJSON method prevents that sibling method from being promoted.

func (NoUnmarshalJSON) UnmarshalJSON

func (NoUnmarshalJSON) UnmarshalJSON([]byte) error

UnmarshalJSON should never be called. It exists only to prevent a sibling UnmarshalJSON method from being promoted.

type Path

type Path []any

Path is a GraphQL response path. Each segment is either a string field name or an integer list index.

func (Path) MarshalJSON

func (p Path) MarshalJSON() ([]byte, error)

MarshalJSON encodes string and integer path segments in GraphQL wire format.

func (Path) String

func (p Path) String() string

String formats a path using dotted fields and bracketed list indexes.

func (*Path) UnmarshalJSON

func (p *Path) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes GraphQL string and integer path segments.

type Payload

type Payload struct {
	Query         string `json:"query"`
	OperationName string `json:"operationName"`
	Variables     any    `json:"variables,omitempty"`
}

Payload is the GraphQL request body used by generated clients.

type RateLimit

type RateLimit struct {
	Limit      int
	Remaining  int
	Used       int
	Reset      time.Time
	Resource   string
	RetryAfter time.Duration
	RetryAt    time.Time
}

RateLimit describes the rate-limit headers returned by GitHub.

Missing or malformed response headers leave their corresponding fields at their zero values.

type RateLimitError

type RateLimitError struct {
	Kind      RateLimitKind
	RateLimit RateLimit
	Err       error
}

RateLimitError describes a response rejected because of a GitHub rate limit.

Example
package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"

	"github.com/willabides/octoql"
)

type exampleViewerResponse struct {
	Viewer struct {
		Login string `json:"login"`
	} `json:"viewer"`
}

type exampleViewerPartialDataError struct {
	data *exampleViewerResponse
	err  error
}

func (e *exampleViewerPartialDataError) Error() string { return e.err.Error() }
func (e *exampleViewerPartialDataError) Unwrap() error { return e.err }
func (e *exampleViewerPartialDataError) PartialData() *exampleViewerResponse {
	return e.data
}

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
		writer.Header().Set("Retry-After", "30")
		_, err := io.WriteString(writer, `{"errors":[{"message":"slow down"}]}`)
		if err != nil {
			panic(err)
		}
	}))
	defer server.Close()

	client := octoql.NewClient(server.URL, server.Client())
	_, err := getViewer(context.Background(), client)

	rateLimitError, ok := errors.AsType[*octoql.RateLimitError](err)
	fmt.Println(ok)
	fmt.Println(rateLimitError.Kind)
}

func getViewer(
	ctx context.Context,
	client *octoql.Client,
) (*exampleViewerResponse, error) {
	return executeExample[exampleViewerResponse](
		ctx,
		client,
		"Viewer",
		"query Viewer { viewer { login } }",
		func(data *exampleViewerResponse, err error) error {
			return &exampleViewerPartialDataError{data: data, err: err}
		},
	)
}

func executeExample[T any](
	ctx context.Context,
	client *octoql.Client,
	operationName string,
	query string,
	newPartialDataError func(*T, error) error,
) (*T, error) {
	response := new(T)
	hasData, err := client.Execute(ctx, octoql.Payload{
		OperationName: operationName,
		Query:         query,
	}, response)
	if !hasData {
		return nil, err
	}
	if err != nil {
		return nil, newPartialDataError(response, err)
	}
	return response, nil
}
Output:
true
secondary

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

Error returns a summary of the rate-limit failure.

func (*RateLimitError) Unwrap

func (e *RateLimitError) Unwrap() error

Unwrap exposes the response failure and its GraphQL or processing causes.

type RateLimitKind

type RateLimitKind string

RateLimitKind identifies the GitHub rate limit that rejected a request.

const (
	// RateLimitPrimary identifies exhaustion of GitHub's primary rate limit.
	RateLimitPrimary RateLimitKind = "primary"
	// RateLimitSecondary identifies GitHub's secondary rate limit.
	RateLimitSecondary RateLimitKind = "secondary"
)

type ResponseError

type ResponseError struct {
	// StatusCode is the HTTP response status.
	StatusCode int
	// RequestID is GitHub's X-GitHub-Request-ID value, when present.
	RequestID string
	// RawBody contains at most the first 64 KiB of a non-successful, over-limit,
	// or undecodable response. It is omitted for ordinary GraphQL errors.
	RawBody []byte
	// RawBodyTruncated reports whether RawBody omits trailing response bytes.
	RawBodyTruncated bool
	// contains filtered or unexported fields
}

ResponseError describes a failed GraphQL HTTP response.

Example
package main

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"

	"github.com/willabides/octoql"
)

type exampleViewerResponse struct {
	Viewer struct {
		Login string `json:"login"`
	} `json:"viewer"`
}

type exampleViewerPartialDataError struct {
	data *exampleViewerResponse
	err  error
}

func (e *exampleViewerPartialDataError) Error() string { return e.err.Error() }
func (e *exampleViewerPartialDataError) Unwrap() error { return e.err }
func (e *exampleViewerPartialDataError) PartialData() *exampleViewerResponse {
	return e.data
}

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
		writer.Header().Set("X-GitHub-Request-ID", "request-example")
		writer.WriteHeader(http.StatusForbidden)
		_, err := io.WriteString(
			writer,
			`{"errors":[{"type":"FORBIDDEN","message":"request rejected"}]}`,
		)
		if err != nil {
			panic(err)
		}
	}))
	defer server.Close()

	client := octoql.NewClient(server.URL, server.Client())
	_, err := getViewer(context.Background(), client)

	responseError, ok := errors.AsType[*octoql.ResponseError](err)
	if !ok {
		fmt.Println("response error not found")
		return
	}
	graphqlErrors, ok := errors.AsType[octoql.Errors](err)
	if !ok {
		fmt.Println("graphql errors not found")
		return
	}

	fmt.Println(responseError != nil)
	fmt.Println(responseError.StatusCode)
	fmt.Println(responseError.RequestID)
	fmt.Println(graphqlErrors[0].Type)
}

func getViewer(
	ctx context.Context,
	client *octoql.Client,
) (*exampleViewerResponse, error) {
	return executeExample[exampleViewerResponse](
		ctx,
		client,
		"Viewer",
		"query Viewer { viewer { login } }",
		func(data *exampleViewerResponse, err error) error {
			return &exampleViewerPartialDataError{data: data, err: err}
		},
	)
}

func executeExample[T any](
	ctx context.Context,
	client *octoql.Client,
	operationName string,
	query string,
	newPartialDataError func(*T, error) error,
) (*T, error) {
	response := new(T)
	hasData, err := client.Execute(ctx, octoql.Payload{
		OperationName: operationName,
		Query:         query,
	}, response)
	if !hasData {
		return nil, err
	}
	if err != nil {
		return nil, newPartialDataError(response, err)
	}
	return response, nil
}
Output:
true
403
request-example
FORBIDDEN

func (*ResponseError) Error

func (e *ResponseError) Error() string

Error returns a stable summary of the failed response.

func (*ResponseError) Unwrap

func (e *ResponseError) Unwrap() error

Unwrap exposes decoded GraphQL errors and response processing failures to errors.Is, errors.As, and errors.AsType.

type ResponseSizeLimitError

type ResponseSizeLimitError struct {
	// Limit is the configured maximum response size in bytes.
	Limit int64
}

ResponseSizeLimitError reports that a GraphQL HTTP response exceeded Client's configured response-size limit.

func (*ResponseSizeLimitError) Error

func (e *ResponseSizeLimitError) Error() string

Error reports that the response exceeded its configured limit.

Directories

Path Synopsis
cmd
octoqlgen command
octoqlgen generates type-safe Go GraphQL clients.
octoqlgen generates type-safe Go GraphQL clients.
octoqlgen/internal/cli
Package cli defines the octoqlgen command-line interface.
Package cli defines the octoqlgen command-line interface.
octoqlgen/internal/config
Package config loads octoqlgen configuration files.
Package config loads octoqlgen configuration files.
octoqlgen/internal/schema
Package schema verifies and materializes pinned GraphQL schemas.
Package schema verifies and materializes pinned GraphQL schemas.
internal
generatefeatures/clientgetter
Package clientgetter exercises generated client getters and custom contexts.
Package clientgetter exercises generated client getters and custom contexts.
generatefeatures/githubdefaults
Package githubdefaults exercises generated helpers that use GitHub's default scalar bindings.
Package githubdefaults exercises generated helpers that use GitHub's default scalar bindings.
generatefeatures/nocontext
Package nocontext exercises generated helpers configured without a context parameter.
Package nocontext exercises generated helpers configured without a context parameter.
handlertest
Package handlertest exercises generated clients and typed test handlers.
Package handlertest exercises generated clients and typed test handlers.
handlertest/localfixture
Package localfixture generates a client and handler-local types for parity tests.
Package localfixture generates a client and handler-local types for parity tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL