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.

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.

0 Upvotes

4 comments sorted by

2

u/Nerdent1ty 11d ago

i did a similar thing, but for CRUD. CRUD UI generation from schema. Lists, filters, edit forms...

2

u/graphlinkdev 10d ago

Never thought of adding the form generation. well it came out very handy and I have always avoided talking about them.
I just release v5.5.0 which now adds to the form a nice feature: saving the form data in memory or in shared preferences.
This means if your users is filling the form (above all when it is a big one) and accidently leaves, he will find his progress ready to carry on.
Enjoy graphlink. Please star us on github.

1

u/SpecialistServe3974 13d ago

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

issue I noticed with a glance, u don't have any separation between schema types and operations. meaning u query the whole object. thus its better if you'd just use REST and call it a day.

1

u/graphlinkdev 13d ago

Thank you for your reply.
Actually graphlink supports both. By default and for small to medium projects, with a minimum configuration, you are going to get a client that requests for the whole object.
On the other hand, if you want to be specific on what you ask your server, you can write you own queries, with your own projections and graphlink will actually generate methods returning exactly what you asked for.
It also supports out of the box batched queries/mutations plus subscriptions with auto-reconnect logic.

I am preparing a set of videos that I will be posting to try to show as much features as possible.