Автогенерация api для RTK Query, graphql, postgraphile и postgresql

0a3feb3180bfd7f6e2dcb71cb370c7d1

Дисклеймер: код испольуемый в данной статье предназначен исключительно для демонстрационных целей.

Исходный код можно найти здесь

Предусловие:

  • имеется GraphQL API сервер. В данном примере, его адрес: http://localhost:5001/graphql. Он реализован с помощью postgraphile. Его настройка и запуск описаны ниже.

Клиентское приложение создадим на основе vitejs и react

npm create vite@latest client -- --template react-ts

Для автогенерации api RTK Query предоставляет плагин @graphql-codegen/typescript-rtk-query

Для его использования нам понадобится еще несколько пакетов. Для этого в директории нашего клиентского приложения выполним:

npm i -D @graphql-codegen/cli \
@graphql-codegen/introspection \
@graphql-codegen/near-operation-file-preset \
@graphql-codegen/typescript-rtk-query \
@rtk-query/graphql-request-base-query

В разделе scripts в package.json добавим:

    "graphql-codegen": "graphql-codegen --config codegen.yml"

Теперь в корне директории нашего клиентского приложения добавим файл настроек для автогенерации codegen.yaml:

overwrite: true
schema: "http://localhost:5001/graphql"
documents: "src/**/*.graphql"
watchConfig:
  usePolling: true
  interval: 1000
generates:
  src/app/services/types.generated.ts:
    plugins:
      - typescript
    config:
      maybeValue: T # normally, this would be T | null, but our msw mock returns everything as nullable, so we want to force these as non-nullalbe
  src/:
    preset: near-operation-file
    presetConfig:
      baseTypesPath: app/services/types.generated.ts
    plugins:
      - add:
          content: >
            /* eslint-disable */
            /**
             *
             * THIS FILE IS AUTOGENERATED, DO NOT EDIT IT!
             *
             * instead, edit one of the `.graphql` files in this project and run
             *
             * npm run graphql-codegen
             *
             * for this file to be re-created
             */
      - typescript-operations
      - typescript-rtk-query:
          importBaseApiFrom: "../../app/services/baseApi"
          exportHooks: true
    config:
      maybeValue: T # normally, this would be T | null, but our msw mock returns everything as nullable, so we want to force these as non-nullalbe
  .introspection.json:
    plugins:
      - introspection

После этого нужно проверить наличие в директории src файлов, содержащих запросы qraphql: query, mutation.
В этом примере, это файлы в директории src/features/todos:

src/features/todos
├── createTodo.graphql
├── deleteTodo.graphql
├── getTodos.graphql
└── updateTodoById.graphql

Также следует убедиться, что сервер работает и находится по адресу, указанному в конфигурации.
Создадим файл src/app/services/baseApi.ts следующего содержания:

import { createApi } from "@reduxjs/toolkit/query/react";
import { graphqlRequestBaseQuery } from "@rtk-query/graphql-request-base-query";
import { GraphQLClient } from "graphql-request";

export const client = new GraphQLClient("/api/graphql");

export const api = createApi({
  baseQuery: graphqlRequestBaseQuery({ client }),
  endpoints: () => ({}),
});

В папке src/features/todos добавим файлы graphql запросов:
createTodo.graphql

mutation createTodo($description: String = "") {
  createTodo(input: { todo: { description: $description } }) {
    todo {
      description
      id
    }
  }
}

getTodos.graphql

query getTodos {
  allTodos {
    nodes {
      id
      description
      completed
    }
  }
}

deleteTodo.graphql

mutation deleteTodoById($id: Int = 10) {
  deleteTodoById(input: { id: $id }) {
    todo {
      description
      id
    }
  }
}

После этого выполним:

npm run graphql-codegen

Вывод команды при успешном выполнении:

> client@0.0.0 graphql-codegen
> graphql-codegen --config codegen.yml

✔ Parse Configuration
✔ Generate outputs

В результате выполнения должны сгенерироваться следующие файлы:

src
├── app
│   └── services
│       └── types.generated.ts
└── features
    └── todos
        ├── createTodo.generated.ts
        ├── deleteTodo.generated.ts
        ├── getTodos.generated.ts
        └──updateTodoById.generated.ts

Пример использования можно посмотреть здесь

Для этого в директории проекта выполните:

docker-compose up -d

А затем в директории /client:

npm run dev

© Habrahabr.ru