gqlkit
Generates typed GraphQL client SDKs for Go and TypeScript with compile-checked field selection.
go get github.com/ubgo/gqlkit/gqlkit
- Language
- Go
- Go version
- 1.25.5
- Core deps
- 1 direct
- Latest tag
- 3 streams
- License
- Apache-2.0
- Go modules
- 8
How it fits together
Highlights from the README
- Type-safe field selection — every field and argument you select is checked against the schema at compile time, in both languages. In TypeScript the result type is also narrowed to the selection, so reading an unselected field is a compile error; in Go the result is the full struct and unselected fields hold zero values
- Builder pattern — fluent API for queries, mutations, arguments, and nested field selection
- Go + TypeScript — generate SDKs for both languages from the same schema
- Single-request batching (Go + TypeScript) — merge multiple query or mutation builders into one aliased GraphQL operation via
batch.RunQueries/batch.RunMutations(Go) orbatch()(TS) — one HTTP round trip for N operations, partial-success aware - Schema introspection — fetch schemas from any GraphQL endpoint with
gqlkit-sdl - Custom scalar mappings — configure how GraphQL scalars map to language types via
config.jsonc - Zero runtime overhead — generated code with minimal dependencies; the Go SDK imports only the standard library plus any package a scalar binding names (such as
github.com/google/uuid)
Code from the README
import (
"yourmodule/sdk/fields"
"yourmodule/sdk/graphqlclient"
"yourmodule/sdk/inputs"
"yourmodule/sdk/queries"
)
client := graphqlclient.NewClient("https://your-api.example.com/graphql",
graphqlclient.WithAuthToken("YOUR_TOKEN"),
)
qr := queries.NewQueryRoot(client)
boolPtr := func(b bool) *bool { return &b } // optional input fields are pointers
todos, err := qr.Todos().
Filter(&inputs.TodoFilter{Done: boolPtr(false)}).
Select(func(f *fields.TodoFields) {
f.ID().Text().Done().User(func(u *fields.UserFields) {
u.ID().Name()
})
}).
Execute(ctx)import { GraphQLClient } from "gqlkit-ts";
import { QueryRoot } from "./sdk/queries";
const client = new GraphQLClient("https://your-api.example.com/graphql", {
authToken: "YOUR_TOKEN",
});
const qr = new QueryRoot(client);
const todos = await qr
.todos()
.filter({ done: false })
.select((t) =>
t.id().text().done().user((u) => u.id().name())
)
.execute();// GQLKit — one type, used everywhere
users, _ := qr.Users().Select(func(u *fields.UserFields) { u.ID().Name().Email() }).Execute(ctx)
user, _ := qr.User().ID("1").Select(func(u *fields.UserFields) { u.ID().Name().Email() }).Execute(ctx)
// Both return types.User// Lightweight list view — only fetch what you need
qr.Todos().Select(func(f *fields.TodoFields) { f.ID().Text() }).Execute(ctx)
// Detail view — same query, more fields, no codegen step
qr.Todos().Select(func(f *fields.TodoFields) {
f.ID().Text().Done().Priority().Tags().User(func(u *fields.UserFields) {
u.ID().Name().Email().Role()
})
}).Execute(ctx)From the gqlkit README.
At a glance (from the README)
| Module | Statement coverage | Command |
|---|---|---|
gqlkit | 94.9% | cd gqlkit && GOWORK=off go test -cover ./... |
gqlkit-sdl | 96.0% | cd gqlkit-sdl && GOWORK=off go test -cover ./... |