graphlink 4.6.0
graphlink: ^4.6.0 copied to clipboard
GraphLink is a powerful code generation tool that generates type-safe client and server code from GraphQL schemas for Dart, Java, Spring Boot and more.

GraphLink #
Define your GraphQL schema once. Get a fully typed client and server scaffold — for Dart, Flutter, Java, TypeScript, and Spring Boot — in milliseconds.
No runtime. No boilerplate. No schema drift.
GraphLink is a CLI tool (glink) that reads a .graphql file and writes production-ready, idiomatic code for your target language. The generated files have zero dependency on GraphLink itself — delete it tomorrow, everything still compiles.
Why GraphLink? #
No generics at the Java call site.
Every other Java GraphQL client makes you write TypeReference<GraphQLResponse<Map<String,Object>>>. GraphLink generates fully-resolved return types:
// Other clients
GraphQLResponse<Map<String, Object>> res = client.query(QUERY_STRING, vars, new TypeReference<>() {});
Vehicle v = objectMapper.convertValue(res.getData().get("getVehicle"), Vehicle.class);
// GraphLink
GetVehicleResponse res = client.queries.getVehicle("42");
System.out.println(res.getGetVehicle().getBrand());
Cache control belongs in your schema.
Declare caching once with @glCache and @glCacheInvalidate — the generated client handles TTL, tag-based invalidation, partial query caching, and offline fallback automatically.
Only what the server needs. GraphLink generates minimal, precise query strings. No full-schema dumps that break Spring Boot's strict GraphQL validation.
Single source of truth.
One .graphql file drives the Dart client, the Java client, and the Spring Boot controllers + service interfaces. Add a field once, regenerate, and both ends stay in sync.
Supported targets #
| Target | Status |
|---|---|
| Dart client | Stable |
| Flutter client | Stable |
| Java client | Stable |
| Spring Boot server | Stable |
| TypeScript client | Stable |
| Express / Node.js | Planned |
| Go, Kotlin | Planned |
Installation #
Download the single self-contained binary — no JVM, no package manager required.
# macOS (ARM)
curl -fsSL https://github.com/Oualitsen/graphlink/releases/latest/download/glink-macos-arm64 -o glink
chmod +x glink && sudo mv glink /usr/local/bin/glink
# Linux (x64)
curl -fsSL https://github.com/Oualitsen/graphlink/releases/latest/download/glink-linux-x64 -o glink
chmod +x glink && sudo mv glink /usr/local/bin/glink
Also available: glink-macos-x64, glink-linux-arm64, glink-windows-x64.exe
→ All releases
Flutter / Dart projects can also use the Dart package:
flutter pub add --dev graphlink
# or
pub add --dev graphlink
Quick Start #
1. Write your schema #
type Vehicle {
id: ID!
brand: String!
model: String!
year: Int!
fuelType: FuelType!
}
enum FuelType { GASOLINE DIESEL ELECTRIC HYBRID }
input AddVehicleInput {
brand: String!
model: String!
year: Int!
fuelType: FuelType!
}
type Query {
getVehicle(id: ID!): Vehicle! @glCache(ttl: 120, tags: ["vehicles"])
listVehicles: [Vehicle!]! @glCache(ttl: 60, tags: ["vehicles"])
}
type Mutation {
addVehicle(input: AddVehicleInput!): Vehicle! @glCacheInvalidate(tags: ["vehicles"])
}
2. Configure #
Create a glink.json (or glink.yaml / glink.yml) in your project root:
{
"schemaPaths": ["schema/*.graphql"],
"mode": "client",
"typeMappings": { "ID": "String", "Float": "double", "Int": "int", "Boolean": "bool" },
"outputDir": "lib/generated",
"clientConfig": {
"dart": {
"packageName": "my_app",
"generateAllFieldsFragments": true,
"autoGenerateQueries": true
}
}
}
Or the equivalent YAML:
schemaPaths:
- schema/*.graphql
mode: client
typeMappings:
ID: String
Float: double
Int: int
Boolean: bool
outputDir: lib/generated
clientConfig:
dart:
packageName: my_app
generateAllFieldsFragments: true
autoGenerateQueries: true
3. Generate #
glink # auto-discovers glink.json / glink.yaml / glink.yml
glink -c config.json # explicit config path
glink -w # watch mode — regenerate on every save
That's it. You get typed classes, a ready-to-use client, JSON serialization, and cache wiring — all generated.
Usage #
Dart / Flutter #
// Initialize — one line with generated adapters
final client = GraphLinkClient.withHttp(
url: 'http://localhost:8080/graphql',
wsUrl: 'ws://localhost:8080/graphql',
tokenProvider: () async => await getAuthToken(), // optional
);
// Query — fully typed, no casting
final res = await client.queries.getVehicle(id: '42');
print(res.getVehicle.brand); // Toyota
print(res.getVehicle.fuelType); // FuelType.GASOLINE
// Mutation
final added = await client.mutations.addVehicle(
input: AddVehicleInput(brand: 'Toyota', model: 'Camry', year: 2023, fuelType: FuelType.GASOLINE),
);
// Subscription
client.subscriptions.vehicleAdded().listen((e) => print(e.vehicleAdded.brand));
Java #
// One-liner init — Jackson + Java 11 HttpClient auto-configured
GraphLinkClient client = new GraphLinkClient("http://localhost:8080/graphql");
// Query — no generics, no casting
GetVehicleResponse res = client.queries.getVehicle("42");
System.out.println(res.getGetVehicle().getBrand());
// Mutation — builder pattern
client.mutations.addVehicle(
AddVehicleInput.builder()
.brand("Toyota").model("Camry").year(2023).fuelType(FuelType.GASOLINE)
.build()
);
// List
List<Vehicle> vehicles = client.queries.listVehicles().getListVehicles();
TypeScript #
import { GraphLinkClient } from './generated/client/graph-link-client';
import { GraphLinkFetchAdapter } from './generated/client/graph-link-fetch-adapter';
const client = new GraphLinkClient(
new GraphLinkFetchAdapter('http://localhost:8080/graphql').call.bind(adapter),
);
// Query — fully typed
const res = await client.queries.getVehicle({ id: '42' });
console.log(res.getVehicle.brand); // Toyota
console.log(res.getVehicle.fuelType); // FuelType.GASOLINE
// Mutation
const added = await client.mutations.addVehicle({
input: { brand: 'Toyota', model: 'Camry', year: 2023, fuelType: FuelType.GASOLINE },
});
// Subscription
client.subscriptions.vehicleAdded({
onData: (e) => console.log(e.vehicleAdded.brand),
});
Spring Boot (server mode) #
Set "mode": "server" and GraphLink generates controllers, service interfaces, types, inputs, and enums:
// Generated — implement this interface
public interface VehicleService {
Vehicle getVehicle(String id);
List<Vehicle> listVehicles();
Vehicle addVehicle(AddVehicleInput input);
Flux<Vehicle> vehicleAdded(); // subscriptions use Reactor Flux
}
// Generated — wires directly into Spring GraphQL
@Controller
public class VehicleServiceController {
@QueryMapping
public Vehicle getVehicle(@Argument String id) { return vehicleService.getVehicle(id); }
// ...
}
Just implement the service interface — the routing is done.
Built-in Caching #
Cache control lives in the schema, not scattered through your application code.
type Query {
# Cache for 2 minutes, tagged "vehicles"
getVehicle(id: ID!): Vehicle! @glCache(ttl: 120, tags: ["vehicles"])
# Serve stale data when offline instead of throwing
getUserProfile(id: ID!): UserProfile @glCache(ttl: 60, staleIfOffline: true)
}
type Mutation {
# Evicts all "vehicles" cache entries on success
addVehicle(input: AddVehicleInput!): Vehicle! @glCacheInvalidate(tags: ["vehicles"])
# Wipe everything
resetData: Boolean! @glCacheInvalidate(all: true)
}
Cache entries are keyed by operation name + variables — each unique argument combination is cached independently. The generated client handles all of it automatically. Bring your own persistent store by implementing GraphLinkCacheStore.
How It Compares #
| Feature | GraphLink | ferry (Dart) | Apollo (JS/Kotlin) | Manual |
|---|---|---|---|---|
| Runtime dependency | ✅ None | ❌ Yes | ❌ Yes | ✅ None |
| Sends whole schema per request | ✅ No | ❌ Yes | ⚠️ Partial | ✅ No |
| Generics at Java call site | ✅ No | ➖ N/A | ❌ Yes | ❌ Yes |
| Server-side generation | ✅ Yes | ❌ No | ⚠️ Partial | ❌ Manual |
| Java client | ✅ Yes | ❌ No | ⚠️ Kotlin only | ❌ Manual |
| Cache directives in schema | ✅ Yes | ❌ No | ❌ No | ❌ No |
| Spring Boot controller gen (MVC) | ✅ Yes | ❌ No | ❌ No | ❌ Manual |
| Spring Boot controller gen (WebFlux) | ✅ Yes | ❌ No | ❌ No | ❌ Manual |
Documentation #
Full documentation at graphlink.dev
- Getting Started — install, first schema, run generator
- Dart / Flutter Client — adapters, queries, mutations, subscriptions
- Java Client — no-generics API, builder pattern, adapters
- TypeScript Client — fetch/axios, RxJS observables, Angular/React/Vue
- Spring Boot Server — controllers, service interfaces, subscriptions
- Caching —
@glCache,@glCacheInvalidate, partial caching, offline - Directives Reference — all 13 directives with examples
- Configuration Reference — every config key explained
License #
MIT — see LICENSE.
Issues and contributions welcome at github.com/Oualitsen/graphlink.