Files
runners-calendar/docs/backend.md
Anton 8eaf006906
Some checks failed
CI / build-and-test (pull_request) Has been cancelled
refactor(api): unify /api contract across frontend, nginx, and backend
2026-04-08 11:59:46 +03:00

122 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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: <NAME>`.
**С `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-файле).