Type Safety Galore! Apollo Tooling for your GraphQL Powered App

I do not use Apollo Graph Manager, my schema is hosted somewhere else. Is this still useful for me?

Yes!

This sounds like a lot of work.

It is not.

I do not use Typescript. Here's why.

Type safety !== Typescript

This post is going to skirt around the TS vs JS debate πŸ™

Code can be generated for other targets including Scala, Swift, Flow, and Typescript. I use it in a Typescript + React Native project. If you have integrated GraphQL into your client-side app, are using any of the targets supported, and are wondering about type safety, this post is for you.


Prerequisites

This guide assumes you have a basic grasp of GraphQL and Apollo Client, and is not meant for the absolute beginner. Beginners can start their journey by completing this excellent full-stack tutorial provided by Apollo which covers everything from creating a graph to building a React-powered client and consuming said graph.

Make sure you have:

  1. Set up your app with GraphQL and Apollo Client.
  2. Set up a β€œdotenv” file for secrets if your server needs an authorization header. I will use dotenv in this guide.
  3. Made your GraphQL endpoint accessible overlocalhost or on a remote server e.g. on Heroku

Installation

Installing packages

Let us start by installing the necessary packages.

# Yarn
yarn add -D apollo dotenv      
# npm   
npm i -D apollo dotenv

Configuring Apollo

The quickest way to configure Apollo is with a config file at the root of our project. Optionally create a dotenv file if you do not already have one.

# make sure you are at the project root
cd <PROJECT_ROOT> 
touch apollo.config.js
touch .env

Paste the following in apollo.config.js. This configures our endpoint and authorization header using environment variables. Add GRAPHQL_ENDPOINT and BEARER_TOKEN in your .env.

require("dotenv").config()
module.exports = {
  client: {
    service: {
      url: process.env.GRAPHQL_ENDPOINT,
      headers: {
        "Authorization": "Bearer " + process.env.BEARER_TOKEN,
      },
    },
  },
}

We are almost done. πŸ˜‰

No, seriously. All we need to do now is configure a package.json script and we are all done.

Configuring package.json

Add this line to the scripts section in your package.json:

"codegen": "apollo codegen:generate <output_path> --includes=<files_to_include> --target <your_target> --outputFlat"

That looks like a lot to digest at first glance, so here is a breakdown:

  • <output_path>: Where we want the generated types to end up in our project structure.
  • <files_to_include>: Glob pattern which Apollo will use to find GraphQL queries and fragments for which types will be generated.
  • <your_target>: One of (scala | flow | swift | typescript), the supported target types. β€” outputFlat: Put generated files in the output directory instead of next to the source file. Entirely optional, so we are free to choose what directory structure we want.

Here is an example in case you get confused by the myriad of options and want to tweak an existing command:

"codegen": "apollo codegen:generate app/generated/types/ --includes='./app/**/*.ts?(x)' --target typescript --outputFlat"

That's it!


One config file, one package.json script and a couple of dependencies later, code generation is set up. You can easily commit the generated types and keep secrets such as authorization tokens and endpoints safe.

Thanks for reading! πŸ₯‚