DEV Community

CodeNameGrant
CodeNameGrant

Posted on • Edited on

GraphQL Code Generator with TypeScript, React and Apollo Client

GraphQL Code Generator is a powerful, open-source, plugin-based tool for streamlining your development by generating boilerplate code from a GQL schema. It can automate the generation of

  • Typed Queries, Mutations and, Subscriptions for React, Vue, Angular, Next.js & Svelte, whether you are using Apollo Client, URQL or, React Query.
  • Typed GraphQL resolvers, for any Node.js (GraphQL Yoga, GraphQL Modules, TypeGraphQL or Apollo) or Java GraphQL server.
  • … And more!

This was my first experience with GraphQL (GQL) and the codegen tool so I'm going to start with what my situation is and how I went about installing and configuring it to serve my use case. I'll include links to additional info as I go.

My Setup

The web apps I work on are written in React and TypeScript. We recently migrated some of our servers to use GraphQL instead of REST, so naturally I turned to Apollo Client and started writing react hooks that extended the native useQuery or useMutation hooks in Apollo.

Example
import { gql, useQuery } from '@apollo/client';

const CHARACTERS_QUERY = gql`
  query GetCharacters {
    characters {
      results {
        name
        origin {
          name
        }
      }
    }
  }
`;

export default function useCharacters() {
  return useQuery(CHARACTERS_QUERY);
}
Enter fullscreen mode Exit fullscreen mode

This approach became a problem though because obviously the queries were not type safe and so I would need to write out all the TypeScript types, its also a pain to extend! As the application/s grow, I kept manually writing these query/mutation hooks, which became time consuming. There is however a way to use TypeScript with Apollo Client which in turn lead me to the GraphQL Code Generator.

Generating Types

Source Repo
The first step I had to take was to generate the TypeScript types from the GQL schema.

Install the generator's CLI as well as the TypeScript plugin

npm i -D @graphql-codegen/cli @graphql-codegen/typescript
Enter fullscreen mode Exit fullscreen mode

Add a script to your package.json execute the generator

scripts: {
  ...
  "codegen": "graphql-codegen"
}
Enter fullscreen mode Exit fullscreen mode

Create the config file in your root directory named codegen.ts

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

const config: CodegenConfig = {
  overwrite: true,
  schema: "https://rickandmortyapi.com/graphql",
  generates: {
    "src/graphql/generated/graphql.ts": {
      plugins: ['typescript'],
    }
  }
};

export default config;
Enter fullscreen mode Exit fullscreen mode

This config will inform the generator to use the Rick & Morty API to generate a file (graphql.ts) using the TypeScript plugin. This will result in the GQL schema being converted into basic TypeScript Types.

Generate React/Apollo Hooks

Source Repo
The next step will instruct the generator to use predefined queries (or mutations) to generate hooks that execute the queries using Apollo Client.

Install the TypeScript-Operations and TypeScript React Apollo plugins.

npm i -D @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
Enter fullscreen mode Exit fullscreen mode

Create src/graphql/documents.graphql to store the queries to generate hooks for.

query Episodes {
  episodes {
    results {
      episode
      name
    }
  }
}

query Characters {
  characters {
    results {
      name
      species
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Update the codegen.ts file to use the above file and plugins to generate the result

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

const config: CodegenConfig = {
  overwrite: true,
  schema: "https://rickandmortyapi.com/graphql",
  documents: './**/*.graphql',
  generates: {
    "src/graphql/generated/graphql.ts": {
      plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
    },
    config: {
      withHooks: true
    }
  }
};

export default config;
Enter fullscreen mode Exit fullscreen mode

The GQL documents can take different patterns. However, after some experimentation, I found that for my use case its easier to just keep them all together in a .graphql file. The config attribute is where plugin attributes are specified. The withHooks attribute is used by typescript-react-apollo.

npm run codegen
Once you have run the generator again, you will see that the generated graphql.ts file now contains hooks that execute the various query variants from Apollo based on the queries we declared, ie useEpisodesQuery, useEpisodesLazyQuery, useEpisodesSuspenseQuery, etc.

Generate Hooks near operational files

Source Repo

As I'm sure you noticed from the source code, the app is structured with feature directories but our types and hooks are all generated in single file. However, I want the types to be in their own file to be used anywhere in the app but the documents and generated hooks must be in the feature directories where they are being used.

To achieve this, I used the Near Operation File Preset plugin. This plugin scans a directory for documents and generates the hooks files in the same location.

First install the plugin

npm i -D @graphql-codegen/near-operation-file-preset
Enter fullscreen mode Exit fullscreen mode

In order to use this preset, you need to add 2 outputs to your codegen.ts file:

  • The first, is the base types, generated by typescript plugin.
  • The second, is the one that is in charge of generating types per document.
import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  overwrite: true,
  schema: '',

  generates: {
    './src/types.ts': {
      plugins: ['typescript']
    },
    './src/': {
      documents: './**/*.graphql',
      preset: 'near-operation-file',
      presetConfig: {
        extension: '.generated.ts',
        baseTypesPath: 'types.ts'
      },
      plugins: ['typescript-operations', 'typescript-react-apollo'],
      config: {
        withHooks: true
      },
    }
  }
};

export default config;
Enter fullscreen mode Exit fullscreen mode

npm run codegen
This will result in a *.generated.ts file being created for each .graphql in any directory under src.

Final Thoughts

The GraphQL Code Generator is in fact a powerful tool that has simplified my development process. It has a large plugin library that supports many languages and presets and is generally well documented.

Top comments (0)