freshcrate
Home > Infrastructure > graphlink

graphlink

Type-safe code generator for GraphQL schemas — produces clients and server interfaces for Dart, Flutter, Java, and Spring Boot. Features built-in caching with TTL/tag-based invalidation, JSO

Description

Type-safe code generator for GraphQL schemas — produces clients and server interfaces for Dart, Flutter, Java, and Spring Boot. Features built-in caching with TTL/tag-based invalidation, JSON serialization, and auto-generated fragments.

README

GraphLink

GraphLink

Define your GraphQL schema once. Get a fully typed client and server scaffold — for Dart, Flutter, Java, and Spring Boot — in seconds.

pub.dev License: MIT GitHub Releases


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

{
  "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 -c config.json        # once
glink -c config.json -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();

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 Yes No No Manual

Documentation

Full documentation at graphlink.dev


License

MIT — see LICENSE.

Issues and contributions welcome at github.com/Oualitsen/graphlink.

Release History

VersionChangesUrgencyDate
v4.5.1**Full Changelog**: https://github.com/Oualitsen/graphlink/compare/v4.5.0...v4.5.1High4/21/2026
v4.5.0## What's Changed * feature/typescript-client by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/182 * fix/interface-union-query-response-deserialization by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/183 * Examples/full ts frameworks by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/184 * feature/generated-code-lint-improvements by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/185 * feature/typescript-client-4.5.0 by @Oualitsen in https://github.coHigh4/19/2026
v4.4.1**Full Changelog**: https://github.com/Oualitsen/graphlink/compare/v4.4.0...v4.4.1High4/18/2026
v4.4.0## What's Changed * site-update 4.3.0 by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/154 * update-readme-md-file by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/157 * Input mappings creation by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/158 * refactor-gl-mapping by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/159 * fix-default-dart-wesocket-adapter by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/160 * upload-support-spring-boot-Medium4/14/2026
v4.3.1**Full Changelog**: https://github.com/Oualitsen/graphlink/compare/v4.3.0...v4.3.1Medium4/4/2026
v4.3.0## What's Changed * immutable-field-configuration by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/123 * add-cache-directives by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/124 * implement-dart-client-cache-handling by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/125 * cache-tags-must-be-alphanumeric by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/126 * disallow @gqCache/@gqNoCache on mutations and subscriptions by @Oualitsen in https://githuMedium3/31/2026
v4.2.0## What's Changed * immutable-field-configuration by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/123 * add-cache-directives by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/124 * implement-dart-client-cache-handling by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/125 * cache-tags-must-be-alphanumeric by @Oualitsen in https://github.com/Oualitsen/graphlink/pull/126 * disallow @gqCache/@gqNoCache on mutations and subscriptions by @Oualitsen in https://githuMedium3/23/2026

Dependencies & License Audit

Loading dependencies...

Similar Packages

MoLiāš™ļø Simplify your projects with MoLi, a fast and flexible Molang interpreter in Java, designed for easy integration and high performance.main@2026-04-21
tonikPure Dart OpenAPI 3.0/3.1 code generator. Creates type-safe API client packages for Dart and Flutter with sealed classes, pattern matching, and full encoding support.tonik-v0.7.0
excalibase-graphqlExcalibase GraphQL instantly turns your database into a GraphQL API. Built with Spring Boot, it supports schema discovery, subscriptions, and type handling — no manual resolvers needed.main@2026-04-19
avaje-httpController generation for Javalin, Helidon SE.3.8
free-claude-codešŸš€ Use Claude Code CLI for free with NVIDIA's unlimited API. This proxy converts requests to NIM format and integrates with a Telegram bot for remote control.main@2026-04-21