# CodeGen: How it simplify your life

Imagine yourself as a chef with a collection of famous dishes. Everyone is asking for the recipes, requiring you to specify the ingredients, quantities, cooking time, preparation time, and much more. Are you gonna tell everyone from scratch?

Hmm.. definitely no. So the answer to this solution is to write a recipe book or post it on the blog. Even if there is any change in the recipe you can update it in one place.

That's exactly what Codegen solves if you're using typescript for frontend development, connecting frontend and backend type, schema and much more in sync.

## Our Goal-

At the end of this article, we will strive to attain an enhanced and seamless development experience something like this-

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1691645202652/d29768b5-fbfd-4084-8262-544a5875d5c5.gif align="center")

But before we start doing crazy stuff with our code let's first try to understand

## Why Do I need Graphql codegen in my project?

If you're using typescript for your frontend, you aim to get every variable to be strictly typed. Let's start with the UI, services and business logic. You can type safely because most of the framework comes with @types/..packages.

**But what about the data you fetch from external services?**

Ok, so you know the external data structure and its types, we can manually define its types no big deal, right? Here is a catch, now imagine if the backend team change any variable type or adds, or deletes new variables, it is almost impossible to keep track and update everywhere.

If you're using GraphQL, you probably know that GraphQL API is typed, and build as a graphQL schema. With the help of graphQL operations (**query/mutation**/f**ragment**/ **subscriptions**), it's the same way we can fetch data on the client-side.

**Before using generated types, let's first try to understand how it works under the hood.**

## How does GraphQL Code Generator work?

In order to generate code and types, GraphQL Code Generator depends on 2 main core concepts **GraphQL Introspection** and **GraphQL AST.**

### **GraphQL Introspection:**

> Introspection is the ability to query which resources are available in the current API schema. Given the API, via introspection, we can see the queries, types, fields, and directives it supports.

**\_\_Schema**

The type \_\_Schema is the one that defines the Schema the API provides. It returns which types the Schema has, the *queryType*, the *mutationType, and the subscriptionType.*

Let's take an example using [Gitthub API](https://docs.github.com/en/graphql/overview/explorer):

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689874930345/de33d394-9cae-4e73-a08e-9a32b0934ca9.png align="right")

**\_\_type**

It represents the type we define in your system. A simple User type is illustrated below-

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689875083003/b2f945fe-d08e-4ea1-8d5b-ad5c10b422f7.png align="center")

**\_\_typename**

It is a reserved field in GraphQL that returns the name of the object type for a particular GraphQL object. `__typename` and `id` plays a significant role as popular clients like Apollo and Relay use it to cache on client-side.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689876034974/1ce688fc-fca0-4d4b-86c8-034c1bac73fe.png align="center")

## GraphQL AST :

> Abstract Syntax tree is a structure that is used in compilers to parse the code we write and convert it into a tree structure that we can traverse programmatically.

When a user makes a request, GraphQL combines the query document that the user requested with the schema definition that we defined for our resolver in the form of an AST. This AST is used to determine which fields were requested, what arguments were included and much more.

After Identifying GraphQL types (schema types and operations ) code generator relies on different sets of plugins to generate specific code snippets and types.

This process applied to the `@graphql-codegen/typescript` plugin, is illustrated below:

![](https://the-guild.dev/graphql/codegen/_next/static/media/codegen_flow1.88e173ec.png align="center")

### GraphQL code generator flow chart

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690175914270/e9237fde-a925-496e-90cc-1f83fc47832c.png align="center")

In the flow chart, we leveraged TypeScript along with TypeScript-Operations and TypeScript-React-Apollo for GraphQL implementation. Additionally, a plethora of other valuable [GraphQL plugins](https://the-guild.dev/graphql/codegen/plugins) are available to further enhance our development experience.

Now we know what GraphQL code generator is, why we need it and how it works let's add it to our project.

# Getting Started

### Step 1: Setup

* Create a new project react/nextJs by running the following command
    
    `npx create-next-app` or,
    

Clone the project by running these commands and skip the next steps-

```plaintext
git clone <git@github.com:RathiAnkxrx/codegen-setup.git>
cd codegen
yarn install
yarn dev
```

### Step 2: Install dependencies

Applications that use [Apollo Client](https://www.apollographql.com/docs/react/why-apollo/) require two main packages `apollo/client` and `graphQL`. Run the following command to install both packages-

```bash
yarn add @apollo/client graphql
```

In our example application, we're going to use Star Wars API

### Step 3: Initialize Apollo Client

```javascript
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
```

Next, we'll ApolloClient and connect out react using `ApolloProvider`, here `uri` is our graphQL server URL, and the cache is an instance of `InMemoryCache`, which Apollo Client use to cache data after fetching them.

```javascript
export default function App({ Component, pageProps }: any) {
  const client = new ApolloClient({
    uri: "https://swapi-graphql.netlify.app/.netlify/functions/index",
    cache: new InMemoryCache(),
  });
  return (
    <ApolloProvider client={client}>
      <Component {...pageProps} />
    </ApolloProvider>
  );
}
```

Apollo Client has been configured. Now to generate relevant `types` of Query and Mutation we need `GraphQL Codegen CLI` as we discussed earlier.

### Step: 4 Instal graphQL Codegen dependencies

Here we're also installing some extra packages for plugins which help to generate query types, ready-to-use hooks and functions.

```bash
yarn add @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo
```

### Step 5: Create a codegen.ts file

In the root directory of your project create a `codegen.ts` file and copy the contents below into this file.

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

const config: CodegenConfig = {
  schema: "https://swapi-graphql.netlify.app/.netlify/functions/index",
  documents: ["src/services/graphql/*.graphql"], // where all graphql queries are written
  ignoreNoDocuments: true, // for better experience with the watcher
  generates: {
    "src/types/graphql.tsx": {
      plugins: [
        "typescript",
        "typescript-operations",
        "typescript-react-apollo",
      ],
      config: {
        skipTypename: false,
        withHooks: true,
        withHOC: false,
        withComponent: false,
      },
    },
  },
};

export default config;
```

Let's first understand what CodegeConfig file contains:

* `schema` your GraphQL server URL
    
* `documents` for larger apps we could have hundreds of queries, to make our code clean we're creating a pagewise query file system.
    
* `src/types/graphql.tsx` where all generated data is stored.
    
* `plugins` following set of plugins are responsible to generate type, hooks and components. Check out more Codegen Plugins available.
    

But what if your API requires a token or you have more than one API, where generated types can't exist at the same folder? The following config will be helpful to achieve that.

```typescript
import type { CodegenConfig } from "@graphql-codegen/cli";
const SCHEMA_URL = "http:/anyUrl/graphql";
const config: CodegenConfig = {
  generates: {
    "src/types/__generated__/withToken/graphql.tsx": {
      documents: "src/services/graphql/withToken/**/*.graphql",
      schema: [
        {
          [SCHEMA_URL]: {
            headers: {
              Authorization:
                "Bearer " + process.env.AUTH_TOKEN,
            },
          },
        },
      ],
      plugins: [...], //same as of previous example
      config: {...},
    },
    "src/types/__generated__/withoutToken/graphql.tsx": {
      documents: "src/services/graphql/withoutToken/**/*.graphql",
      schema: SCHEMA_URL,
      plugins: [...],
      config: {...},
    },
  },
};

export default config;
```

### Step 6: Head to package.json and add this scripts

```bash
 "scripts": {
    ...
    "generate": "graphql-codegen --config codegen.ts"
  },
```

It's finally time to generate types, go ahead and open your terminal and run `yarn generate` or `npm generate`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690909521890/7e7d19f7-4f88-40cc-8daf-f143c0db992b.png align="left")

If you see something like this, Congratulations, you now have the best GraphQL front-end experience with fully-typed Queries and Mutations! Now let's see what we achieved and how to use it.

## Writing GraphQL Queries

Earlier we used `useQuery` hook from `@apollo/client` and pass query inside hook to get data something like this-

```typescript
import { useQuery } from "@apollo/client";
import { gql } from "@apollo/client";

export default function Home() {
  const GET_ALLFILMS = gql`
    query AllFilms {
      allFilms {
        films {
            ...
        }
      }
    }
  `;
  const { data, loading , error } = useQuery(GET_ALLFILMS);
  return <>...</>
}
```

And with the help of generated hooks, we can directly use them instead of `useQuery`

```typescript
import styles from "./styles/page.module.css";
import { useAllFilmsQuery } from "../types/graphql";
export default function Home() {
  const { data , loading , error} = useAllFilmsQuery();
  return  <>...</>
}
```

* `useAllFilmsQuery()` hook get triggered as soon as page URL hits.
    
* If there is a case when you only want to hit query after some action like a button click we have `useAllFilmsLazyQuery`
    

```typescript
import styles from "./styles/page.module.css";
import { useAllFilmsLazyQuery } from "../types/graphql";

export default function Home() {
  const [fetchFilms, {data, loading , error}] = useAllFilmsLazyQuery();
  const handleClick = () => {
    fetchFilms({
      variables : { /// if variable is required 
        }
    });
  };

  return (
    <main className={styles.main}>
      <button onClick={handleClick}>Fetch Films</button>
    </main>
  );
}
```

As data can be deeply nested while traversing down it's very easy to lose track of key pair or due to `null | undefined` value possibility we can easily hit an error which is hard to debug.

The biggest advantage in my opinion of using this approach is type safety and time. Now our IDE’s IntelliSense is able to give us hints about the shape of the data response. This helps us build apps fast and avoids bugs for they’d be caught really early when writing the code.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690912948395/00f32310-b80c-4665-a506-45aa328e7a24.png align="center")

### Generate more than just types

As we discussed earlier we have codegen plugins which help us to generate more than just type and hooks. One of them is `typescript-react-apollo` which is responsible to generate HOC(Higher Order Components) and Query Components.

**React& Apollo: Generate Components**

Go to the codegen.ts file and change `withComponent` to `true`. Run `yarn generate` in terminal

```typescript
 config: {
  skipTypename: false,
  withHooks: true,
  withHOC: false,
  withComponent: true,
  },
```

And then use it in your code:

```typescript
<AllFilmsComponent>
{({ data, loading, error }) => {
  return (
    <div className={styles.grid}>
      {data?.allFilms?.films?.map((film) => {
        return (
          <div key={+Math.random()}>
            <p>{film?.director}</p>
            ...
          </div>
        );
      })}
    </div>
  );
}}
</AllFilmsComponent>
```

### Type destructuring tips:

To access the particular key value of an object there are many ways to do it one of which is `object["someKey"]` using the same concept we are going to destructure types.

In Our case we have `allFilms` inside data to get its type we will first start with data type which is `AllFilmsQuery` (same as your query name which is a query + "QUERY" after the name) and the type of allFilms will be `AllFilmsQuery["allFilms"]`.

But there are times when your external data is deeply nested and some parents could have `null | undefined`. In this very particular example of `allFilms` is an array of something and could be null or undefined.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1691603021499/8217df98-c8bf-4230-ae44-63c0ff9113e1.png align="center")

Then how to get what would be the type of films object. For this, we can not simply use `AllFilmsQyery["allFilms"][0]`.

* First, select NonNullable value of AllFilmsQuery and pick `allFilms` something like this-
    
    ```typescript
    NonNullable<AllFilmsQuery['allFilms']>
    ```
    
* And then using the same logic select films
    
    ```typescript
    NonNullable<NonNullable<AllFilmsQuery["allFilms"]>["films"]>
    ```
    

This method is very useful while looping through data or passing nested values in child components.

### Conclusion:

In this article, we tried to explain why exactly we need codegen in your project, how it works and filled the gap between **GraphQL** and **typescript**.

My aim while creating apps is to make the code readable and simple with the bare minimum of hard work. And this setup helps me to achieve that.

Let me know if you have any questions, suggestions or tips, and share with other people if you find this interesting and can help others.
