Initial commit

This commit is contained in:
2026-04-28 22:51:54 +03:00
commit 3565390a49
76 changed files with 16956 additions and 0 deletions

186
PROJECT_STRUCTURE.md Normal file
View File

@@ -0,0 +1,186 @@
# Структура проекта Polotsk Transit API
## 📁 Обзор директорий
```
polotsk-transit-api/
├── backend/ # Node.js API сервер
│ ├── src/
│ │ ├── config/ # Конфигурация (DB, Redis, Logger)
│ │ ├── controllers/ # Бизнес-логика
│ │ │ ├── routesController.js # Управление маршрутами
│ │ │ ├── stopsController.js # Управление остановками + PostGIS
│ │ │ ├── etaController.js # Расчет ETA
│ │ │ └── syncController.js # Offline синхронизация
│ │ ├── middleware/ # Middleware (Auth, Rate Limiting)
│ │ ├── routes/ # Express маршруты
│ │ └── index.js # Точка входа
│ ├── migrations/ # SQL миграции (PostGIS схема)
│ ├── package.json
│ └── Dockerfile
│
├── frontend/ # React админ-панель
│ ├── src/
│ │ ├── components/ # React компоненты
│ │ │ ├── RouteForm.jsx # Форма маршрута
│ │ │ └── StopForm.jsx # Форма остановки
│ │ ├── pages/ # Страницы
│ │ │ ├── Dashboard.jsx # Главная страница
│ │ │ ├── RoutesPage.jsx # Управление маршрутами
│ │ │ ├── StopsPage.jsx # Остановки + карта Leaflet
│ │ │ └── SchedulesPage.jsx # Расписания (заглушка)
│ │ ├── services/ # API клиент
│ │ ├── App.jsx # Главный компонент + роутинг
│ │ ├── main.jsx # Точка входа
│ │ └── index.css # Tailwind стили
│ ├── package.json
│ ├── vite.config.js
│ └── Dockerfile
│
├── nginx/ # Reverse proxy конфигурация
│ └── nginx.conf # Nginx для API + Admin + SSL
│
├── docker-compose.yml # Оркестрация всех сервисов
├── .env.example # Шаблон переменных окружения
├── .gitignore
├── README.md # Полная документация
└── QUICKSTART.md # Быстрый старт
```
## 🎯 Ключевые файлы
### Backend
**Конфигурация:**
- `backend/src/config/database.js` - PostgreSQL connection pool
- `backend/src/config/redis.js` - Redis клиент для кеширования
- `backend/src/config/logger.js` - Winston logger
**Контроллеры:**
- `backend/src/controllers/routesController.js` - CRUD маршрутов + кеширование
- `backend/src/controllers/stopsController.js` - CRUD остановок + PostGIS геопоиск
- `backend/src/controllers/etaController.js` - Умный расчет времени прибытия
- `backend/src/controllers/syncController.js` - Полная и инкрементальная синхронизация
**Middleware:**
- `backend/src/middleware/auth.js` - API key аутентификация
- `backend/src/middleware/rateLimiter.js` - Rate limiting с Redis
**Миграции:**
- `backend/migrations/001_init.sql` - Полная схема БД с PostGIS
### Frontend
**Страницы:**
- `frontend/src/pages/Dashboard.jsx` - Статистика и быстрый старт
- `frontend/src/pages/RoutesPage.jsx` - Управление маршрутами с карточками
- `frontend/src/pages/StopsPage.jsx` - Карта Leaflet + список остановок
- `frontend/src/pages/SchedulesPage.jsx` - Заглушка для будущего функционала
**Компоненты:**
- `frontend/src/components/RouteForm.jsx` - Форма создания/редактирования маршрута
- `frontend/src/components/StopForm.jsx` - Форма создания/редактирования остановки
**API сервис:**
- `frontend/src/services/api.js` - Axios клиент со всеми endpoints
### Инфраструктура
**Docker:**
- `docker-compose.yml` - 5 сервисов (PostgreSQL, Redis, Backend, Frontend, Nginx)
- `backend/Dockerfile` - Node.js production образ
- `frontend/Dockerfile` - Multi-stage build с Nginx
**Nginx:**
- `nginx/nginx.conf` - Reverse proxy с SSL, rate limiting, безопасностью
## 🔧 Основные технологии
| Компонент | Технология | Назначение |
|-----------|------------|------------|
| API Server | Express.js | REST API |
| База данных | PostgreSQL + PostGIS | Хранение данных + геопространственные запросы |
| Кеш | Redis | Кеширование + pub/sub для WebSocket |
| Frontend | React + Vite | Админ-панель |
| Карты | React Leaflet | Интерактивная карта |
| Стили | Tailwind CSS | Быстрая разработка UI |
| Контейнеризация | Docker Compose | Оркестрация сервисов |
| Reverse Proxy | Nginx | SSL, rate limiting, безопасность |
## 📊 Схема базы данных (кратко)
```sql
routes -- Маршруты (номер, название, тип, цвет)
stops -- Остановки (название, GEOGRAPHY(Point), адрес)
route_stops -- М:М связь маршрутов и остановок (с sequence и time_offset)
schedules -- Расписания (departure_times[], day_type)
vehicles -- Транспортные средства
historical_delays -- Статистика задержек для умного ETA
alerts -- Уведомления и алерты
api_keys -- API ключи для аутентификации
sync_log -- Лог изменений для offline синхронизации
```
## 🚀 Что уже работает
✅ Полный REST API
✅ CRUD для маршрутов и остановок
✅ PostGIS геопространственные запросы (ближайшие остановки)
✅ Расчет ETA на основе расписания + исторических задержек
✅ Offline синхронизация (полная и инкрементальная)
✅ Веб админ-панель с картой
✅ Docker deployment
✅ API key аутентификация
✅ Rate limiting
✅ Кеширование через Redis
✅ Логирование
## 📝 Что добавить в будущем
**Версия 2.0 (Краудсорсинг):**
- [ ] WebSocket для реалтайм GPS
- [ ] Endpoint для приема GPS от пользователей
- [ ] Агрегация и фильтрация GPS данных
- [ ] Функция "Я еду в маршруте"
**Версия 3.0 (Продвинутые функции):**
- [ ] IoT GPS-трекеры
- [ ] ML для предсказания задержек
- [ ] Push уведомления
- [ ] Детальная аналитика
## 💡 Советы по развертыванию
1. **Обязательно смените пароли** в `.env` перед продакшеном
2. **Используйте Cloudflare Tunnel** для скрытия домашнего IP
3. **Настройте SSL** через Let's Encrypt или Cloudflare
4. **Включите fail2ban** для защиты от брутфорса
5. **Настройте бэкапы** PostgreSQL (pg_dump + cron)
6. **Мониторинг** через Docker stats или Prometheus
## 🎓 Интеграция с мобильными приложениями
Используйте эндпоинт `/api/v1/sync` для offline-first подхода:
1. При первом запуске - полная синхронизация (без `lastSync`)
2. При последующих - инкрементальная (с `lastSync=timestamp`)
3. Храните данные локально (SQLite, Realm, Core Data)
4. Обновляйте в фоне каждые 5-10 минут
Пример для iOS:
```swift
func syncData() async {
let lastSync = UserDefaults.standard.object(forKey: "lastSync") as? Date
let params = lastSync != nil ? ["lastSync": ISO8601DateFormatter().string(from: lastSync!)] : [:]
let data = try await api.get("/sync", params: params)
await database.updateLocalData(data)
UserDefaults.standard.set(Date(), forKey: "lastSync")
}
```
---
**Создано для Полоцка 🇧🇾 | MIT License**