---
name: create-graphql-operation
description: |
  Создание GraphQL операции — query или mutation для получения данных или выполнения действий через GraphQL API бэкенда.
  Используй когда нужно добавить новый запрос к API, выполнить действие через mutation, интегрироваться с новым GraphQL endpoint или оптимизировать существующий запрос - запрашивать меньше данных.
---

# Создание GraphQL операции

**GraphQL операция** — это query или mutation для получения данных или выполнения действий через GraphQL API бэкенда. Операции запрашивают только нужные данные, типизируются на основе схемы бэкенда и переиспользуются между провайдерами, gateway и backend-for-frontend слоями.

---

## Критические правила

> **⚠️ ВАЖНО: не редактировать вручную следующие файлы:**
>
> - `types.ts` — типы генерируются автоматически.
> - `schema.graphql` — схема скачивается с бэкенда.
>
> Оба файла обновляются при запуске команды генерации GraphQL-типов.
>
> **Для анализа актуальной GraphQL-схемы**: типы, поля, аргументы — всегда используйте скилл [Интроспекция GraphQL-схемы](../introspect-gql-schema/SKILL.md).
>
> **Локальные `types.ts` и `schema.graphql` не используйте как источник истины по схеме.**

### Правила работы с GraphQL

1. Создавать 2 файла: `.graphql` файл с запросом + `.ts` файл-обёртка в `operations/`.
2. Выносить во фрагменты переиспользуемые блоки данных.
3. Использовать Query / Mutation типы в прикладных типах, редьюсерах и store, не общие типы из схемы.
4. Генерировать типы после каждого изменения `.graphql` файлов.

---

## Предварительные требования

1. **Определить GraphQL проект** — используйте скилл [select-project-from-ticket](../select-project-from-ticket/SKILL.md) для выбора нужного проекта.
2. **Изучить схему через интроспекцию** — проверить доступные типы, поля и аргументы через [introspect-gql-schema](../introspect-gql-schema/SKILL.md).
3. **Проверить существующие фрагменты** — возможно, нужные данные уже описаны во фрагменте.

---

## Структура файлов GraphQL проекта

```text
app/graphql/projects/<project>/
├── queries/                    # Query-запросы
│   └── <category>/
│       └── <QueryName>.graphql
├── mutations/                  # Mutation-запросы
│   └── <category>/
│       └── <MutationName>.graphql
├── fragments/                  # Переиспользуемые фрагменты
│   └── <category>/
│       └── <FragmentName>.graphql
├── operations/                 # TS-обёртки над операциями
│   └── <category>/
│       └── <OperationName>.ts
├── schema.graphql              # ⛔ НЕ РЕДАКТИРОВАТЬ: артефакт codegen, не источник истины
└── types.ts                    # ⛔ НЕ РЕДАКТИРОВАТЬ: генерируется
````

### Доступные проекты

| Проект      | Путь                              | Назначение                  |
| ----------- | --------------------------------- | --------------------------- |
| `MAIN`      | `app/graphql/projects/main/`      | Основной API продукта       |
| `SECONDARY` | `app/graphql/projects/secondary/` | Дополнительный API продукта |
| `GLOBAL`    | `app/graphql/projects/global/`    | Глобальный API              |
| `CRM`       | `app/graphql/projects/crm/`       | CRM / back-office API       |

---

## Пошаговая инструкция

### 1. Определите тип операции

* **Query** — для получения данных: GET-подобные операции.
* **Mutation** — для изменения данных: POST / PUT / DELETE-подобные операции.

### 2. Создайте `.graphql` файл

**Для Query:**

```text
app/graphql/projects/<project>/queries/<category>/<QueryName>.graphql
```

**Для Mutation:**

```text
app/graphql/projects/<project>/mutations/<category>/<MutationName>.graphql
```

### 3. Напишите GraphQL запрос

Запрашивайте только поля, которые реально нужны потребителю операции.

### 4. Создайте фрагменты, если нужно

Выносите повторяющиеся или логически связанные группы полей во фрагменты.

### 5. Создайте TS-обёртку в `operations/`

```text
app/graphql/projects/<project>/operations/<category>/<OperationName>.ts
```

### 6. Сгенерируйте типы

```bash id="nq0qfe"
make gql-generate-types project=<PROJECT_NAME>
```

### 7. Используйте операцию в провайдере, gateway или backend-for-frontend слое

---

## Шаблоны кода

### Query

[`query-example.graphql`](references/query-example.graphql)

### Mutation

[`mutation-example.graphql`](references/mutation-example.graphql)

### Фрагмент

[`fragment-example.graphql`](references/fragment-example.graphql)

### TS-обёртка для query

[`operation-query.ts`](references/operation-query.ts)

### TS-обёртка для mutation

[`operation-mutation.ts`](references/operation-mutation.ts)

---

## Генерация типов

После создания или изменения `.graphql` файлов необходимо сгенерировать TypeScript-типы:

```bash id="jzt2vi"
make gql-generate-types project=<PROJECT_NAME>
```

### Что генерируется

На основе файлов `.graphql` генерируются типы в `types.ts`: Query / Mutation типы и типы переменных.

---

## Использование типов

### В провайдере

[`provider-usage.ts`](references/provider-usage.ts)

Для использования в gateway / backend-for-frontend слое см. [Создание API-гейта](../create-api-gate/SKILL.md).

### В типах редьюсера или store

**Используйте Query / Mutation типы, а не общие типы из схемы:**

```typescript id="8kyb5c"
// ✅ Правильно: использовать Query тип
import { GetEntityQuery } from 'app/graphql/projects/main/types';

type IEntityData = NonNullable<GetEntityQuery['entity']>;

// ❌ Неправильно: использовать общий тип из схемы
// import { Entity } from 'app/graphql/projects/main/types';
```

**Почему это важно:**

* Query тип отражает реально запрашиваемые данные.
* Общий тип содержит все поля из схемы, которые могут не быть в запросе.
* При расширении схемы на бэкенде код не сломается из-за полей, которые текущая операция не запрашивает.

---

## Работа с фрагментами

### Когда создавать фрагмент

* Одни и те же поля запрашиваются в нескольких query / mutation.
* Есть логически связанная группа полей: например, данные автора, карточки, сниппета.
* Есть повторяющаяся вложенная структура.

### Импорт фрагмента

```graphql id="do7i50"
#import "../../fragments/path/to/Fragment.graphql"

query MyQuery {
    entity {
        ...FragmentName
    }
}
```

### Структура файла фрагмента

```graphql id="75d5qn"
# fragments/<category>/<FragmentName>.graphql

fragment FragmentName on TypeName {
    field1
    field2
    nestedField {
        subField
    }
}
```

---

## Чеклист валидации

* [ ] Определён правильный GraphQL проект.
* [ ] Создан `.graphql` файл в `queries/` или `mutations/`.
* [ ] Имя файла соответствует PascalCase: `GetEntityName.graphql`.
* [ ] Созданы фрагменты для переиспользуемых данных.
* [ ] Создана TS-обёртка в `operations/`.
* [ ] Выполнена генерация типов: `make gql-generate-types project=<PROJECT_NAME>`.
* [ ] Используются сгенерированные Query / Mutation типы.
* [ ] Структура схемы проверена через интроспекцию, а не по локальному `schema.graphql`.
* [ ] Не редактировались `types.ts` и `schema.graphql`.

---

## Именование

| Элемент          | Формат     | Пример                       |
| ---------------- | ---------- | ---------------------------- |
| Query файл       | PascalCase | `GetEntityCard.graphql`      |
| Mutation файл    | PascalCase | `CreateEntity.graphql`       |
| Fragment файл    | PascalCase | `EntityCardDetails.graphql`  |
| Operation файл   | PascalCase | `GetEntityCard.ts`           |
| Экспорт операции | PascalCase | `export const GetEntityCard` |
| Query имя        | PascalCase | `query GetEntityCard`        |
| Mutation имя     | PascalCase | `mutation CreateEntity`      |
| Fragment имя     | PascalCase | `fragment EntityCardDetails` |

---

## Связанные скиллы

* [Выбор проекта по задаче](../select-project-from-ticket/SKILL.md) — определение GraphQL проекта.
* [Создание дата-провайдера](../create-data-provider/SKILL.md) — использование query в SSR / data loading.
* [Создание API-гейта](../create-api-gate/SKILL.md) — использование mutation в gateway / backend-for-frontend слое.
* [Создание state-management модуля](../create-state-module/SKILL.md) — типизация данных в store.
