Перейти к содержанию

Примеры навыков

1. Создание React компонентов

Файл: .koda/skills/react-component/SKILL.md
---
name: react-component
description: Создание React компонентов с лучшими практиками
---

# React Component Creation

## Purpose

Создание React компонентов с соблюдением лучших практик проекта.

## When to use

Когда пользователь просит создать React компонент или упоминает "component", "React", "JSX".

## Instructions

### 1. Структура компонента

Всегда создавай компоненты в следующем порядке:

1. **Импорты** — сгруппированные по типу
    ```typescript
    // React
    import React, { FC, useState, useEffect } from 'react';

    // Библиотеки
    import { classNames } from '@/utils';

    // Локальные
    import { Button } from '../Button';
    ```

2. **Типы** — перед компонентом
    ```typescript
    interface ComponentProps {
        title: string;
        onClick?: () => void;
    }
    ```

3. **Компонент** — с явным типом
    ```typescript
    export const MyComponent: FC<ComponentProps> = ({ title, onClick }) => {
        // Логика
        return <div>{title}</div>;
    };
    ```

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

- Используй PascalCase для имён компонентов
- Префикс `use` для хуков: `useAuth`, `useForm`
- Суффикс `Props` для типов пропсов

### 3. Стиль кода

- Используй функциональные компоненты
- Избегай классовых компонентов
- Применяй хуки вместо lifecycle методов
- Типизируй всё через TypeScript

### 4. Тесты

Для каждого компонента создавай тест:
- Файл: `ComponentName.test.tsx`
- Библиотека: React Testing Library
- Покрытие: основные сценарии использования

## Examples

### Пример компонента

    ```typescript
    import React, { FC, useState } from 'react';
    import { Button } from '../Button';

    interface CounterProps {
        initialValue?: number;
    }

    export const Counter: FC<CounterProps> = ({ initialValue = 0 }) => {
        const [count, setCount] = useState(initialValue);

        return (
            <div>
            <p>Count: {count}</p>
            <Button onClick={() => setCount(count + 1)}>
                Increment
            </Button>
            </div>
        );
    };
    ```

2. Python API Best Practices

Файл: .agents/skills/python-api/SKILL.md
---
name: python-api
description: Создание Python API с использованием FastAPI
---

# Python API Development

## Purpose

Создание REST API на Python с использованием FastAPI и соблюдением стандартов проекта.

## When to use

Когда пользователь просит создать API, endpoint, или упоминает "FastAPI", "Python API".

## Instructions

### 1. Структура проекта

    ```
    app/
    ├── main.py              # Точка входа
    ├── api/                 # API роуты
    │   ├── v1/
    │   │   ├── endpoints/
    │   │   └── router.py
    ├── core/                # Конфигурация
    │   ├── config.py
    │   └── security.py
    ├── models/              # SQLAlchemy модели
    ├── schemas/             # Pydantic схемы
    └── services/            # Бизнес-логика
    ```

### 2. Создание endpoint

Всегда следуй шаблону:

    ```python
    from fastapi import APIRouter, Depends, HTTPException
    from sqlalchemy.orm import Session

    from app.core.database import get_db
    from app.schemas import ItemCreate, ItemResponse
    from app.services import item_service

    router = APIRouter()

    @router.post("/items/", response_model=ItemResponse)
    def create_item(
        item: ItemCreate,
        db: Session = Depends(get_db)
    ) -> ItemResponse:
        """
        Create a new item.

        - **name**: Item name (required)
        - **price**: Item price (required, must be positive)
        """
        return item_service.create(db=db, item=item)
    ```

### 3. Валидация

Используй Pydantic для валидации:

    ```python
    from pydantic import BaseModel, Field, validator

    class ItemCreate(BaseModel):
        name: str = Field(..., min_length=1, max_length=100)
        price: float = Field(..., gt=0)

        @validator('name')
        def name_must_not_be_empty(cls, v):
            if not v.strip():
                raise ValueError('name cannot be empty')
            return v
    ```

### 4. Обработка ошибок

    ```python
    from fastapi import HTTPException, status

    def get_item_or_404(db: Session, item_id: int):
        item = db.query(Item).filter(Item.id == item_id).first()
        if not item:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Item not found"
            )
        return item
    ```

## Examples

### Полный пример endpoint

    ```python
    from fastapi import APIRouter, Depends, HTTPException, status
    from sqlalchemy.orm import Session
    from typing import List

    from app.core.database import get_db
    from app.schemas import UserCreate, UserResponse, UserUpdate
    from app.services import user_service
    from app.models import User

    router = APIRouter(prefix="/users", tags=["users"])

    @router.post("/", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
    def create_user(user: UserCreate, db: Session = Depends(get_db)):
        """Create a new user."""
        return user_service.create(db=db, user=user)

    @router.get("/{user_id}", response_model=UserResponse)
    def get_user(user_id: int, db: Session = Depends(get_db)):
        """Get a specific user by ID."""
        return get_item_or_404(db, user_id)

    @router.get("/", response_model=List[UserResponse])
    def list_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
        """List all users with pagination."""
        return db.query(User).offset(skip).limit(limit).all()
    ```

3. Git Commit Messages

Файл: .koda/skills/git-commit/SKILL.md
---
name: git-commit
description: Генерация сообщений коммитов в формате Conventional Commits
---

# Git Commit Messages

## Purpose

Создание сообщений коммитов в стандарте Conventional Commits.

## When to use

Когда пользователь просит сгенерировать commit message или использует команду `/commit`.

## Instructions

### 1. Формат сообщения

    ```
    <type>(<scope>): <description>

    [optional body]

    [optional footer]
    ```

### 2. Типы коммитов

- **feat**: Новая функциональность
- **fix**: Исправление бага
- **docs**: Изменения в документации
- **style**: Форматирование, отступы (без изменений кода)
- **refactor**: Рефакторинг кода
- **test**: Добавление тестов
- **chore**: Изменения в сборке, зависимостях
- **perf**: Улучшение производительности
- **ci**: Изменения в CI/CD
- **build**: Изменения в системе сборки

### 3. Правила

- Заголовок до 50 символов
- Тело до 72 символов на строку
- Используй повелительное наклонение: "add", не "added"
- Не заканчивай точкой
- Указывай breaking changes в footer

### 4. Примеры

**Хорошо**:
    ```
    feat(auth): добавить OAuth2 аутентификацию

    - Интеграция с Google OAuth
    - Добавлены эндпоинты /auth/google
    - Обновлены типы User

    Closes #123
    ```

**Плохо**: `fix: исправил баги и добавил фичи`

## Examples

### Пример для исправления бага

    ```
    fix(api): исправить утечку памяти в WebSocket

    Закрытие соединения не освобождало ресурсы.
    Добавлен явный вызов cleanup() при отключении.

    Fixes #456
    ```

### Пример для новой фичи

    ```
    feat(ui): добавить тёмную тему

    - Реализовано переключение тем
    - Сохранение выбора в localStorage
    - Обновлены цветовые переменные CSS

    BREAKING CHANGE: Изменены названия цветовых переменных
    ```

4. Database Migrations

Файл: .koda/skills/db-migration/SKILL.md
---
name: db-migration
description: Создание миграций базы данных с лучшими практиками
---

# Database Migrations

## Purpose
Создание безопасных миграций базы данных с возможностью отката.

## When to use
Когда пользователь просит создать миграцию, изменить схему БД, или упоминает "migration", "schema".

## Instructions

### 1. Именование файлов

    ```
    YYYYMMDDHHMMSS_description.sql
    ```

Пример:
    ```
    20250115143022_add_users_table.sql
    ```

### 2. Структура миграции

Всегда включай:
- **UP** — применение миграции
- **DOWN** — откат миграции

    ```sql
    -- UP
    CREATE TABLE users (
        id SERIAL PRIMARY KEY,
        email VARCHAR(255) NOT NULL UNIQUE,
        created_at TIMESTAMP DEFAULT NOW()
    );

    CREATE INDEX idx_users_email ON users(email);

    -- DOWN
    DROP INDEX IF EXISTS idx_users_email;
    DROP TABLE IF EXISTS users;
    ```

### 3. Правила

- Всегда пиши DOWN миграцию
- Используй транзакции
- Добавляй индексы для внешних ключей
- Не изменяй существующие данные в UP
- Тестируй откат перед применением

### 4. Безопасные изменения

**Добавление колонки**:
    ```sql
    -- UP
    ALTER TABLE users ADD COLUMN phone VARCHAR(20);

    -- DOWN
    ALTER TABLE users DROP COLUMN phone;
    ```

**Изменение типа колонки**:
    ```sql
    -- UP (сначала новая колонка)
    ALTER TABLE users ADD COLUMN phone_new VARCHAR(20);
    UPDATE users SET phone_new = phone;
    ALTER TABLE users DROP COLUMN phone;
    ALTER TABLE users RENAME COLUMN phone_new TO phone;

    -- DOWN
    ALTER TABLE users ADD COLUMN phone_old VARCHAR(10);
    UPDATE users SET phone_old = phone;
    ALTER TABLE users DROP COLUMN phone;
    ALTER TABLE users RENAME COLUMN phone_old TO phone;
    ```

## Examples

### Миграция с внешним ключом

    ```sql
    -- UP
    CREATE TABLE orders (
        id SERIAL PRIMARY KEY,
        user_id INTEGER NOT NULL,
        total DECIMAL(10,2) NOT NULL,
        created_at TIMESTAMP DEFAULT NOW(),

        CONSTRAINT fk_orders_user
            FOREIGN KEY (user_id)
            REFERENCES users(id)
            ON DELETE CASCADE
    );

    CREATE INDEX idx_orders_user_id ON orders(user_id);
    CREATE INDEX idx_orders_created_at ON orders(created_at);

    -- DOWN
    DROP INDEX IF EXISTS idx_orders_created_at;
    DROP INDEX IF EXISTS idx_orders_user_id;
    DROP TABLE IF EXISTS orders;
    ```