# Backend — эксплуатация ## Стек - **Node.js LTS** + TypeScript - **Express** (HTTP-фреймворк) - **pg** (PostgreSQL клиент) - **csv-parse** (парсинг CSV для seed) ## Быстрый старт ### 1. Поднять PostgreSQL ```bash # из корня проекта docker-compose up -d ``` Параметры подключения берутся из `.env` (см. `.env.example` в корне). ### 2. Установить зависимости ```bash cd backend npm install ``` ### 3. Создать `.env` Скопировать `.env.example` из корня проекта и при необходимости отредактировать: ```bash cp ../.env.example ../.env ``` ### 4. Миграции ```bash npm run db:migrate ``` Миграционный раннер — собственный скрипт `src/migrate.ts`: - хранит историю применённых файлов в таблице `_migrations`; - идемпотентный — повторный запуск не применяет уже выполненные миграции; - файлы миграций: `backend/migrations/*.sql`, применяются в алфавитном порядке. ### 5. Seed (начальный набор данных) ```bash npm run seed ``` - Читает `import/races_2026_calendar.csv` из корня репо. - Генерирует стабильный `id` в формате `{date}-{slug}`. - Выполняет **upsert** (`INSERT … ON CONFLICT DO UPDATE`) — безопасно для повторного запуска. ### 6. Запуск API ```bash npm run dev # dev-режим через ts-node npm run build # компиляция в dist/ npm start # запуск из dist/ ``` API слушает порт: **`PORT`** (если задан), иначе **`API_PORT`**, иначе **`3001`**. ## Переменные окружения | Переменная | Описание | По умолчанию | |---|---|---| | `DB_HOST` | Хост PostgreSQL | — (обязательна без mock, см. ниже) | | `DB_PORT` | Порт PostgreSQL | — (обязательна без mock) | | `DB_NAME` | Имя базы данных | — (обязательна без mock) | | `DB_USER` | Пользователь БД | — (обязательна без mock) | | `DB_PASSWORD` | Пароль БД | — (обязательна без mock) | | `CALENDAR_RUN_MOCK_DB` | `1` или `true` — режим без PostgreSQL для HTTP API (dev/CI) | выкл. | | `PORT` | Порт API (приоритетнее `API_PORT`) | — | | `API_PORT` | Порт API-сервера | `3001` | | `CORS_ORIGIN` | Разрешённый origin для CORS | `http://localhost:5173` | Фронтенд всегда обращается к API по префиксу `/api` на текущем origin. В локальной разработке этот префикс проксирует Vite (`frontend/vite.config.ts`) на `http://localhost:3001`; в Docker-стеке — nginx фронта проксирует на backend. **Без mock:** при отсутствии любой из `DB_*` процесс падает при старте: `Missing required environment variable: `. **С `CALENDAR_RUN_MOCK_DB=1`:** переменные `DB_*` не обязательны; реальный пул не поднимается. **Не использовать** mock для `npm run db:migrate` и `npm run seed` — нужен настоящий Postgres и корректные `DB_*`. ## Поведение при недоступной БД - **Старт сервера** — проходит успешно (env валидирован, Express слушает порт). - **`GET /api/health`** — всегда `200 { "status": "ok" }` (liveness, без обращения к БД). - **`GET /api/ready`** — при обычном режиме пробует подключиться к БД; `200` если ОК, `503 { "error": "database_unavailable", ... }` если нет. В режиме **`CALENDAR_RUN_MOCK_DB`** readiness считается успешным без реального подключения (удобно для CI/smoke API). - **Все остальные маршруты** при ошибке БД возвращают `503 { "error": "database_unavailable" }`. ## Структура каталога ``` backend/ ├── migrations/ │ ├── 001_create_races.sql │ └── 002_finish_place_and_registered_status.sql ├── src/ │ ├── app.ts # фабрика Express (тесты) │ ├── config.ts # загрузка и валидация env │ ├── db.ts # pg Pool или mock │ ├── index.ts # запуск сервера │ ├── migrate.ts # раннер миграций │ ├── seed.ts # разовый импорт CSV │ ├── mappers/ │ │ └── race.ts # snake_case ↔ camelCase │ └── routes/ │ ├── health.ts # /api/health, /api/ready, /api/meta │ └── races.ts # CRUD /api/races ├── package.json └── tsconfig.json ``` ## Docker: стек backend + frontend Файл [`docker-compose.stack.yml`](../docker-compose.stack.yml) поднимает API и nginx со статикой SPA в **внешней** сети Docker (рядом с уже запущенным Postgres). Переменные — в **корневом** `.env` (шаблон [`.env.example`](../.env.example)): как минимум `DB_*`, `CORS_ORIGIN` (для выдачи фронта на порту 3033 задайте `http://localhost:3033`). Перед первым `up` файл `.env` должен существовать. Порядок после старта контейнеров: `node dist/migrate.js` и `node dist/seed.js` внутри контейнера `backend` (см. комментарии в compose-файле).