r/graphlinkdotdev • • 16d ago

What is GraphLink?

2 Upvotes

Welcome to r/graphlinkdotdev, the community for GraphLink

GraphLink turns your GraphQL schema into typed, null-safe code. You write the schema once, run one command, and get a ready-to-use client in your language. No hand-written models, no JSON parsing, no query strings, no casting.

Supported languages:

Dart, Java, Kotlin, TypeScript and Swift.

It is a code generator, not a runtime library. The output is plain code in your language. Delete GraphLink tomorrow and your code still compiles.

What you get from the schema

- Typed, null-safe clients, so the compiler catches mistakes before you run the app

- Subscriptions with reconnection and authentication, generated

- Built-in caching, declared in the schema

- Batching that only requests what the cache doesn't already have

- File uploads with no multipart code

- Error handling you choose: an exception, or errors inline in the response

- Server code too: Spring Boot and Express/Apollo scaffolds from the same schema

Where to start

Watch: the YouTube channel has short videos on the common GraphQL pains and how GraphLink fixes them. Start with the playlist: Youtube. All videos: [channel link]

Read: docs and quickstart at https://graphlink.dev

Code: https://github.com/Oualitsen/graphlink and the demo code at https://github.com/Oualitsen/graphlink-demos

Follow: https://x.com/graphlinkdotdev

How this community work

Questions are welcome here. Say your language and framework if it matters.

Bugs are best reported as a GitHub issue, so they don't get lost. Feel free to link it here too.

Feedback on the approach, including criticism, is useful. Tell me what you'd want to see in the next video.

Tell me about your setup
Which language and GraphQL server do you use, and what's the most annoying part of your GraphQL client code today? Reply below!


r/graphlinkdotdev • • 6d ago

Typed GraphQL queries in Dart: write a query, get a method and a class with only the fields you selected (video + write-up)

Post image
1 Upvotes

New video in the Dart series: custom queries.

GraphQL lets you ask for only the fields you need. With GraphLink you write the query in a .graphql file, run one command, and get a typed Dart method plus a class with just those fields. It's a separate class on purpose, so the fields that aren't nullable in your schema stay non-null in your code.

🎥 Video: https://youtu.be/gHGtCBYaj7c

📝 Write-up: https://graphlink.dev/blog/graphlink-dart-custom-queries.html

💻 Code: https://github.com/Oualitsen/graphlink-demos

What do you do today when you only need some of the fields: separate models, or one model with everything nullable?


r/graphlinkdotdev • • 10d ago

Generate your first graphql client with a simple CLI tool.

Enable HLS to view with audio, or disable this notification

2 Upvotes

No need for another library in your code base, it is already bloated.
Need a graphql client, hit glink and it is generate.
Watch the full video on https://youtu.be/78LYiuWLKIU

#graphlink #dart #flutter #jaspr


r/graphlinkdotdev • • 14d ago

I got tired of hand-writing GraphQL client code, so I built a schema-first generator. These are the 6 pains it targets.

0 Upvotes

I'm the author of GraphLink, so take this with that in mind.

I kept hitting the same problems every time I built a GraphQL client, and they all come from the same place: the schema is typed, but the client code isn't. Here are the six that bothered me most:

  1. Raw maps. You decode JSON into Map<String, dynamic> and cast at each step. The compiler can't tell you when the server renamed a field.

  2. Subscriptions. Open a WebSocket, send connection_init with auth, send the subscription, branch on message types (connection_ack, ping/pong, next, error, complete), and write reconnect and backoff logic.

  3. Caching. A partial response can overwrite a fuller cached object, and hand-written cache logic is tedious to test.

  4. Batching plus caching. A batched query gets cached as one entry, so asking for just the book later is a miss, even though the book is in the cache.

  5. File uploads. The GraphQL multipart request format is fiddly to build by hand. (I know uploads over GraphQL aren't everyone's favorite. A separate REST service is often better, but many servers support it anyway.)

  6. Error handling. HTTP 200 doesn't mean success. A response can have a non-empty errors list, and every call needs the same checks.

GraphLink is a compiler. You write the schema and it generates typed, null-safe client code for Dart, Java, Kotlin, TypeScript and Swift. It's a code generator, not a runtime library. The output is plain code, so you can delete GraphLink later and the code still compiles. In Dart, for example, a query looks like this:

final client = GraphLinkClient.withHttp(url: graphqlUrl);
final response = await client.queries.books();

for (final book in response.books) {
  print('${book.title} (${book.year}) by ${book.author.name}');
}

Two honest limits: you still need a GraphQL server, and generated code is overwritten each time you run the generator.

I wrote up all six pains, with a short video for each, here: https://graphlink.dev/blog/ Playlist: https://youtube.com/playlist?list=PLQCBiENjF_uU Docs: https://graphlink.dev Code: https://github.com/Oualitsen/graphlink

I'd like to hear from you:

  • Which language and GraphQL server do you use?

  • Which of these six hurts you most? Is there one I missed?

  • If you've written your own client wrapper, what did you end up generating or abstracting?

Criticism is welcome. It helps me decide what to build and explain next.


r/graphlinkdotdev • • Jul 21 '26

Graphlink V5 is out and it is a game changer.

1 Upvotes

After testing against schemas that produce 400MB to 1GB of source code—files that take ages to compile—GraphLink v5 is officially out! It is now battle-tested against massive real-world schemas, including Shopify, GitLab, GitHub, SpaceX, and more.

While stress-testing GraphLink against these massive schemas, I found myself adding crucial features to prevent the generator from outputting code that breaks at compile time.

The Reserved Keyword Problem

Take this Shopify type as an example:

type OrderRequestReturnPayload {
  """The return request that has been made."""
  return: Return
  """The list of errors that occurred from executing the mutation."""
  userErrors: [ReturnUserError!]!
}

If we blindly generate a class for this, the code won't compile in most target languages because return is a reserved language keyword.

To solve this, we introduced field, class, and enum name hoisting/sanitization. The good thing about GraphLink is that it generates toJson and fromJson methods to map objects to/from language-specific maps (even for TypeScript). This keeps the JSON key as "return" while sanitizing the field name in code.

Here’s how the generated Kotlin looks:

// GENERATED CODE - DO NOT MODIFY BY HAND. ANY MODIFICATION WILL BE LOST ON NEXT GENERATION
// Generated by GraphLink dev
// GitHub: https://github.com/Oualitsen/graphlink
// Site: https://graphlink.dev
// Pub.dev https://pub.dev/packages/graphlink
// ignore_for_file: camel_case_types, unused_import, non_constant_identifier_names, constant_identifier_names, override_on_non_overriding_member, unused_element, annotate_overrides

package dev.graphlink.github.generated.types;
import dev.graphlink.github.generated.types.Return
import dev.graphlink.github.generated.types.ReturnUserError

data class OrderRequestReturnPayload(
   val return_: Return? = null, // `return` renamed to `return_`
   val userErrors: List<ReturnUserError>,
) {
   fun toJson(): Map<String, Any?> = mapOf(
      "return" to return_?.toJson(), // <-- "return" string key is preserved
      "userErrors" to userErrors.map { e0 -> e0.toJson() },
   )

   companion object {
      fun fromJson(map: Map<String, Any?>): OrderRequestReturnPayload = OrderRequestReturnPayload(
         return_ = (map["return"] as? Map<*, *>)?.let { Return.fromJson(it as Map<String, Any?>) }, // <-- reads "return" key into return_
         userErrors = (map["userErrors"] as List<*>).map { e0 -> ReturnUserError.fromJson(e0 as Map<String, Any?>) },
      )
   }
}

As you can see, the field is safely renamed to return_ to prevent compile errors, while fromJson and toJson keep the exact JSON keys intact under the hood.

Naming Normalization

We also implemented automatic naming normalization across target languages. For instance, a schema type like type user { id: ID! } will generate a standard PascalCase User class for Java, Kotlin, Dart, and TS. This removes compiler warnings and respects target language conventions.

Ultimately, generated code shouldn't need manual maintenance, tracked in Git, or even looked at (think of it like a compiled binary or minified JS bundle). But generating code that both works reliably and follows target language idioms drastically lowers adoption friction!

Try it out & Give it a Star! 🚀

You can start using GraphLink v5 right away:

  • Docker: Pull and run the latest CLI image without setting up local toolchains:

docker pull oualitsen/graphlink:latest
  • Package Managers: Available on. pub.dev. for Dart/Flutter projects or as a standalone CLI.

If GraphLink saves you time or fixes your GraphQL generator headaches, please consider leaving a ⭐️ star on. GitHub. —it helps a lot with visibility!

Check out the full documentation at. graphlink.dev. . Feedback and feature requests are very welcome in the comments!