/graphql-codegen-react-query

Generating react-query hooks and typescript types from a graphql schema

Primary LanguageTypeScriptMIT LicenseMIT

graphql-codegen-react-query

Open in Visual Studio Code npm bundle size Github workflow Quality Gate Status Maintainability Rating Security Rating Reliability Rating Coverage Lines of Code Technical Debt Code Smells Bugs Vulnerabilities Snyk Vulnerabilities for npm package Duplicated Lines (%) Last commit

Generating types and react-query hooks from a graphql schema.

            

⚡ Purpose

Graphql codegen is a great tool; zeus-graphql is a neat lib. But they don't exactly fit what I want 😿

🤔 I want to get clean typescript artifacts from my graphql schema

🤔 I want type enforcing for args, params and results while using useQuery and useMutation hooks

🤔 I want to easily import what I need from generated code

🤔 When using a query, I want to pick what I want as result when I only need a subset of the query result

🤔 But I also want to be able to easily pick everything if that's what I need

🤔 I want to define which queries should be translated into infinite queries

So here we go, I just figured I'd do something for giggles 🤷.

⚡ What is generated exactly ?

codegen step

⚡ Get started

🔶 Install

To install, use either pnpm, yarn or npm:

yarn add -D graphql-codegen-react-query

🔶 Setup

Let's setup our codegen tooling by running the codegen-init command:

yarn codegen-init

This command takes three optional parameters:

Parameter Description Default value
c Where to write the codegen config file . (current folder)
o Where generated code should be written ./api
u Graphql api url. If it doesn't start with http, the variable will be treated as an environment variable name http://localhost:3333/graphql

So if I need to use custom params, I'd do:

yarn gqlCodegen-init -c ./libs/graphql/codegen/src -o libs/graphql/artifacts/src/api -u NEXT_PUBLIC_GQL_API_URL

🗯️ This command generates two files:

  • The react-query.codegen.yml config file.
  • The fetcher hook. You might need to inject config in the fetching logic, like setting an Authorization header for example; that is why the fetching logic is externalized in this hook.

The config file typically looks like this:

# Where generate code should be written
outputPath: 'libs/graphql/artifacts/src/api/codegen'
# The environment variable name containing the url to the graphql schema (or directly said url)
schemaUrl: NEXT_PUBLIC_GQL_API_URL
# Fetcher hook config
fetcher:
  # Path to the fetcher, relative to the generated queries/mutations
  path: './../../useFetchData'
  # fetcher hook name (expecting a named export)
  functionName: 'useFetchData'
# Queries that should be generated as infinite queries with react-query
infiniteQueries:
  - useProductsByPage

🔶 Codegen

🚨 Make sure introspection is enabled on the backend you target

Generating types from a graphql schema is easy enough using cli. Usage is as follows:

gqlCodegen -c [configFilePath]

Options:
      --help     Show help                                             [boolean]
      --version  Show version number                                   [boolean]
  -c             Codegen config file path
                               [required] [default: "./react-query.codegen.yml"]

Examples:
  gqlCodegen -c ./libs/graphql/react-query.codegen.yml

With that in mind, we can add a script to our package.json:

{
  [...],
  "scripts:" {
    "codegen": "gqlCodegen -c ./libs/graphql/react-query.codegen.yml",
    [...]
  }
}

⚡ Features

🔶 Clean types

From a schema like this...

enum GqlOrderedItemStatus {
  preparing
  readyToBeSent
  shippingInProgress
  shipped
}
type GqlOrderedItem {
  id: ID!
  quantity: Int!
  name: String!
  image: String
  price: Float!
  status: GqlOrderedItemStatus!
}
type GqlOrder {
  id: ID!
  idUser: ID!
  idCreditCard: ID!
  createdAt: DateTime!
  creditCardNumber: String!
  items: [GqlOrderedItem!]!
}

I expect to get this:

export type GqlOrderedItemStatus = 'preparing' | 'readyToBeSent' | 'shippingInProgress' | 'shipped'

export interface GqlOrderedItem {
  id: string;
  quantity: number;
  name: string;
  image?: string;
  price: number;
  status: GqlOrderedItemStatus
}
export interface GqlOrder {
  id: string;
  idUser: string;
  idCreditCard: string;
  createdAt: Date;
  creditCardNumber: string;
  items: Array<GqlOrderedItem>;
}

🔶 Dynamic selection and result type inference

It would be great if I could use named query hooks (one react hook by graphql query) but still be able to select what I want in the result 🤔

For example, for a schema like this, I should have a named query hook useCategoriesQuery with type inference:

type GqlProduct {
  id: ID!
  idCategory: ID!
  name: String!
  description: String!
  image: String!
  price: Float!
  stock: Int!
}

type GqlCategoryWithProducts {
  id: ID!
  name: String!
  products: [GqlProduct!]
}


type Query {
  categories: [GqlCategoryWithProducts!]!
}

dynamic selection

If i want the entire query result, I can use useCategoriesQuery instead of useCategoriesPartialQuery:

dynamic selection

🔶 Dynamic queries

It would be neat if I could get the results from several graphql queries by calling one single react hook 🤔

Let's use the useGqlQuery hook that does just that:

dynamic selection

🔶 Queries/Mutations variables type support

I would be nice if I had strong typings for arguments and results 🤔

dynamic selection

🔶 Queries/Mutations options

It would be awesome if I could still easily tweak react query hooks 🤔

dynamic selection