The new GraphQL Code Generator Client Preset

7 Nov 2022

GraphQL Code Generator recently changed how it handles configuration, and plugins.

Configuration can now be done using the new file codegen.ts where you can now import types to help complete the configuration.

You may have previously configured plugins to generate hooks for your framework, or even a TypedDocumentNode but now GraphQL Code Generator ships with a new "client preset".

All of the plugins we were used to previously have moved to a new community repository where users can still use them, but the new client preset is now the preferred way of making type-safe GraphQL apps.

We'll install the dependencies inside of a new project, but you could follow along inside of your existing project:

npm install --save-dev typescript @graphql-codegen/cli @graphql-codegen/client-preset

Finally don't forget to install graphql itself as a dependency:

npm install graphql

For the purposes of this tutorial we'll manually configure the codegen.ts file:

Inside the root of your project create the file codegen.ts:

touch codegen.ts

Inside here we will import CodegenConfig and export a new config object:

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {};

export default config;

We'll now pass the GraphQL API where it can fetch the schema:

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "https://api.cartql.com",
};

export default config;

This schema could be a file, or a collection of files.

If your schema was protected using an API key, you can adjust the configuration to look like this:

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: [
    {
      ["URL_HERE"]: {
        headers: {
          KEY: "VALUE",
        },
      },
    },
  ],
};

export default config;

Next we'll add the documents that the GraphQL Code Generator must watch and generate types from. We'll say this is any tsx and ts files in the folder app:

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "https://api.cartql.com",
  documents: ["app/**/*.{ts,tsx}"],
};

export default config;

Since we don't have any documents yet, we'll pass true to ignoreNoDocuments so we don't get started with any errors:

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "https://api.cartql.com",
  documents: ["app/**/*.{ts,tsx}"],
  ignoreNoDocuments: true,
};

export default config;

Then all that's left to do to finish configuring the GraphQL Code Generator is to provide the generates config. Here we'll generate the folder gql in the root of our project and use he preset client without any plugins:

import { CodegenConfig } from "@graphql-codegen/cli";

const config: CodegenConfig = {
  schema: "https://api.cartql.com",
  documents: ["app/**/*.{ts,tsx}"],
  ignoreNoDocuments: true,
  generates: {
    "./gql/": {
      preset: "client",
      plugins: [],
    },
  },
};

export default config;

Next we'll add to our package.json a new script that runs the GraphQL Code Generator in watch mode. This will generate types for any GraphQL queries and mutations as you write them!

{
  "scripts": {
    "codegen": "graphql-codegen --watch"
  }
}

If you now execute the codegen script we should see that the folder gql was generated in the root of our project with some default files.

npm run codegen

Now all that's left to do is update app/client.ts to include a GraphQL operation.

You will want to import graphql from ./gql and pass our GraphQL query to that:

import { graphql } from "../gql";

const GetCartByIdDocument = graphql(/ *GraphQL */`
  query GetCartById($id: ID!) {
    cart(id: $id) {
      id
      totalItems
    }
  }
`);

Once you save this file it will automatically update the files inside ./gql to include the correctly typed TypedDocumentNode for the query GetCartById.

That's it! The query is now fully typed and can be used with any GraphQL client that uses the TypedDocumentNode. We'll learn more about those and fragments in another tutorial.