GraphQL Type Generation in Flutter

Intro

Nearly a year ago I was experimenting with GraphQL at the backend as well as frontend side. I fell in love with it instantly. The kind of possibilities it enabled was endless (mostly at the frontend side). I tried using Apollo + React and they worked great. But when I looked at the flutter side, there were no good packages. graphql_flutter was pretty new and there were no good type generation libraries even if there were there was a lack of documentation as well as examples. One year later, we have a ton of great libraries for GraphQL clients in dart and flutter. Let’s take a look at one of the examples.

Goals

  • Generate dart classes from GraphQL schema.
  • Autocomplete and validation of GraphQL queries.
  • Use a GraphQL client to fetch data. In this case, we would be using because it is already imported and works pretty well with generated types, but feel free to use any client of your choice.
  • Display the result using the power of flutter.

Prerequisites

  • Make sure you have flutter installed on your system
  • Setup the IDE of your choice. I will be using Visual studio code.

Let’s Start

We would be working with endpoint to fetch pokemons. You can get the schema file from here. You will need this to generate types.

Packages

We would be installing the following packages.

  • for type generation as well client. If you are using any other client and just need type generations you can add artemis in the dev dependencies.
  • for generating dart code.
  • for generating toJson and fromJson methods. artemis will do it on its own,
dependencies:
artemis: ^7.0.0-beta.9
dev_dependencies:
build_runner: ^2.0.2
json_serializable: ^4.1.1

Artemis Type Generation

1. GraphQL Query

It is a simple GraphQL query that will fetch a list of pokemons from GraphQL endpoint.

query fetch_pokemons($quantity: Int!){
pokemons(first:$quantity){
id
name
image
classification
types
maxCP
maxHP
}
}

Create a file fetchpokemons.query.graphql inside project/graphql and save it there.

2. buil.yaml

First, we will write the build.yaml which artemis will use as configuration for generating types.

targets:
$default:
sources:
- lib/**
- graphql/**
- pokemon.schema.graphql
builders:
artemis:
options:
schema_mapping:
- schema: pokemon.schema.graphql
queries_glob: graphql/fetchpokemons.query.graphql
output: lib/graphql/fetch_pokemons_query.dart

— Here you define things related to the queries, mutations, or subscriptions, like which schema to use, location of the queries, location of fragments, location of output files, etc.

If you have any different GraphQL data type and you want to convert it to a dart type you define it in . Example of converting GraphQL DateTime to dart DateTime. You will write a custom converter if required. You need to implement both and constant functions.

Place this inside the root directory of your project,

3. Run the build runner command

Run the following command in the terminal to generate the types. If everything worked fine you would see some auto-generated code in lib/graphql.

flutter pub run build_runner build

It generates everything from query document to fromJson and toJson methods to types for the result as well as arguments type and much more.

Flutter Part

All that left is to make a simple UI and send a request.

It is probably not the best looking UI but we can work with that.

Here is the function to fetch the data.

Final result

screen recording of the app

Tips

  • If you have nested objects inside your GraphQL query use fragments to avoid long type names, which you can refer to in your code [ObjectName]Mixin.
  • You can replicate the behavior of copyWith methods by doing something like
extension NewInstance on ClassMixin {
ClassMixin jsonCopyWith() {
return Class.fromJson(
(this as Class).toJson());
}
}
  • Prefer storing all the queries generated using the schema in one place to avoid the generation of duplicate types.

Conclusion

As you can see using artemis for generating data types for our GraphQL schema saved us a lot of time, our code is less prone to bugs and requires less testing. You can find the source code at