feat: Add all improvements - Winston, Validator, Rate Limit, Docker, CI/CD, Documentation
Some checks are pending
CI/CD / lint-and-build (push) Waiting to run

This commit is contained in:
DosAi 2025-11-02 16:47:30 +03:00
parent da1de34d21
commit 77e30fdaa4
15 changed files with 742 additions and 75 deletions

48
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,48 @@
# GitHub Actions CI/CD workflow
name: CI/CD
on:
push:
branches: [main, dev]
pull_request:
branches: [main]
jobs:
lint-and-build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install frontend dependencies
working-directory: ./frontend
run: npm ci
- name: Run ESLint
working-directory: ./frontend
run: npm run lint
- name: Check Prettier formatting
working-directory: ./frontend
run: npm run format:check
- name: Build frontend
working-directory: ./frontend
run: npm run build
- name: Install backend dependencies
working-directory: ./backend
run: npm ci
- name: Check backend syntax
working-directory: ./backend
run: node --check server.js

7
.gitignore vendored
View File

@ -47,3 +47,10 @@ next-env.d.ts
Thumbs.db
.DS_Store
# Logs
logs/
*.log
# Docker
.dockerignore

21
Dockerfile Normal file
View File

@ -0,0 +1,21 @@
# Dockerfile для backend (Node.js)
FROM node:20-alpine
WORKDIR /app
# Копируем package.json и устанавливаем зависимости
COPY backend/package*.json ./
RUN npm install --production
# Копируем код приложения
COPY backend/ .
# Создаем папку для логов
RUN mkdir -p logs
# Открываем порт
EXPOSE 3001
# Запускаем приложение
CMD ["node", "server.js"]

30
Dockerfile.frontend Normal file
View File

@ -0,0 +1,30 @@
# Dockerfile для frontend (Next.js статический экспорт)
FROM node:20-alpine AS builder
WORKDIR /app
# Копируем package.json и устанавливаем зависимости
COPY frontend/package*.json ./
RUN npm install
# Копируем код и собираем
COPY frontend/ .
RUN npm run build
# Production стадия - сервинг статических файлов
FROM node:20-alpine
WORKDIR /app
# Устанавливаем serve для статических файлов
RUN npm install -g serve
# Копируем собранные файлы
COPY --from=builder /app/out ./out
# Открываем порт
EXPOSE 3000
# Запускаем serve
CMD ["serve", "-s", "out", "-p", "3000"]

View File

@ -1,6 +1,6 @@
# Рекомендации по улучшению шаблона
## Добавленные улучшения
## ✅ Реализованные улучшения
### 1. Prettier для форматирования кода
- Конфигурация `.prettierrc`
@ -13,77 +13,81 @@ npm run format # Форматировать весь код
npm run format:check # Проверить форматирование
```
### 2. Переменные окружения
### 2. Переменные окружения (dotenv)
- `.env.example` файлы для frontend и backend
- Автоматическая загрузка через `dotenv`
- Шаблоны для быстрого старта
- Документация в файлах
### 3. Middleware для бэкенда
- `logger.js` - логирование всех запросов
- `logger.js` - простое логирование всех запросов
- `errorHandler.js` - централизованная обработка ошибок
- Пример использования в `server.js`
- Интегрировано в `server.js`
### 4. Структура роутов
- Пример файла `routes/example.js`
### 4. Продвинутое логирование (Winston)
- Структурированные логи в файлы
- Разные уровни логирования
- Логи в `backend/logs/`
- Конфигурация в `backend/config/logger.js`
### 5. Валидация запросов (Express Validator)
- Middleware `validate.js` для обработки валидации
- Примеры валидации в `routes/example.js`
- Валидация body, params, query
### 6. Rate Limiting (Express Rate Limit)
- Два уровня защиты: общий и строгий
- Настраиваемые лимиты
- Защита от злоупотреблений
### 7. Структура роутов
- Пример файла `routes/example.js` с валидацией
- Организация API endpoints по модулям
- Готовый шаблон для новых роутов
### 5. Пример компонента
### 8. Пример компонента
- `ExampleComponent.tsx` с использованием API
- Демонстрация работы с состоянием
- Обработка ошибок и загрузки
## Дополнительные рекомендации
### 9. Docker поддержка
- `Dockerfile` для backend
- `Dockerfile.frontend` для frontend
- `docker-compose.yml` для разработки
- `.dockerignore` для оптимизации
### Можно добавить в будущем:
### 10. CI/CD (GitHub Actions)
- Автоматическая проверка кода
- Проверка линтера и форматирования
- Проверка сборки
- Workflow в `.github/workflows/ci.yml`
1. **Валидация запросов** (express-validator)
```bash
npm install express-validator
```
## 📚 Документация
2. **Логирование** (winston или pino)
```bash
npm install winston
```
### Создана полная документация:
- [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) - Подробное руководство по всем улучшениям
- [`docs/QUICK_START.md`](docs/QUICK_START.md) - Быстрый старт
- [`docs/PROJECT_RULES.md`](docs/PROJECT_RULES.md) - Правила разработки
- [`docs/KNOWLEDGE_BASE.md`](docs/KNOWLEDGE_BASE.md) - База знаний
3. **Валидация окружения** (dotenv-safe)
```bash
npm install dotenv-safe
```
## 🎯 Использование улучшений
4. **Rate limiting** (express-rate-limit)
```bash
npm install express-rate-limit
```
Все улучшения готовы к использованию. См. [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) для подробных инструкций по каждому улучшению.
5. **TypeScript для бэкенда**
## 🔮 Дополнительные возможности (опционально)
1. **TypeScript для бэкенда**
- Переименовать `.js` в `.ts`
- Настроить `tsconfig.json` для backend
- Добавить типы для Express
6. **Docker поддержка** (опционально)
- `Dockerfile` для frontend и backend
- `docker-compose.yml`
7. **Тестирование** (опционально)
2. **Тестирование**
- Jest для unit тестов
- Testing Library для компонентов
8. **CI/CD** (GitHub Actions)
- Автоматическая проверка кода
- Автоматический деплой
## Текущая структура
Все основные улучшения уже добавлены:
- ✅ Prettier
- ✅ Environment variables examples
- ✅ Middleware структура
- ✅ Примеры роутов
- ✅ Пример компонента
- ✅ Логирование
- ✅ Обработка ошибок
Шаблон готов к использованию и может быть расширен по мере необходимости.
3. **База данных**
- Подключение к PostgreSQL/MySQL
- ORM (Prisma, Sequelize)
4. **Аутентификация**
- JWT токены
- Passport.js стратегии

View File

@ -152,6 +152,19 @@ npm run format:check # Проверить форматирование
- `frontend/.env.example``frontend/.env.local`
- `backend/.env.example``backend/.env`
### Улучшения шаблона
Шаблон включает следующие улучшения:
- ✅ **Winston** - продвинутое логирование
- ✅ **Express Validator** - валидация запросов
- ✅ **Express Rate Limit** - защита от злоупотреблений
- ✅ **dotenv** - управление переменными окружения
- ✅ **Docker** - контейнеризация приложения
- ✅ **GitHub Actions** - CI/CD автоматизация
Подробные инструкции: [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md)
Быстрый старт: [`docs/QUICK_START.md`](docs/QUICK_START.md)
## 📝 Лицензия
ISC

40
backend/config/logger.js Normal file
View File

@ -0,0 +1,40 @@
// Конфигурация Winston для логирования
const winston = require('winston');
const logFormat = winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.errors({ stack: true }),
winston.format.splat(),
winston.format.json()
);
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: logFormat,
defaultMeta: { service: 'backend' },
transports: [
// Запись ошибок в файл
new winston.transports.File({
filename: 'logs/error.log',
level: 'error'
}),
// Запись всех логов в файл
new winston.transports.File({
filename: 'logs/combined.log'
}),
],
});
// В режиме разработки также выводить в консоль
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize(),
winston.format.simple()
),
}));
}
module.exports = logger;

View File

@ -0,0 +1,31 @@
// Rate limiter для защиты от злоупотреблений
const rateLimit = require('express-rate-limit');
// Общий rate limiter
const generalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 минут
max: 100, // максимум 100 запросов с одного IP за окно времени
message: {
success: false,
error: 'Too many requests from this IP, please try again later.',
},
standardHeaders: true,
legacyHeaders: false,
});
// Строгий rate limiter для API
const strictLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 20, // максимум 20 запросов
message: {
success: false,
error: 'Too many requests, please try again later.',
},
});
module.exports = {
generalLimiter,
strictLimiter,
};

View File

@ -0,0 +1,24 @@
// Middleware для валидации запросов с express-validator
const { validationResult } = require('express-validator');
const validate = (validations) => {
return async (req, res, next) => {
// Выполняем все валидации
await Promise.all(validations.map(validation => validation.run(req)));
const errors = validationResult(req);
if (errors.isEmpty()) {
return next();
}
res.status(400).json({
success: false,
error: 'Validation failed',
errors: errors.array(),
});
};
};
module.exports = validate;

View File

@ -13,7 +13,11 @@
"license": "ISC",
"dependencies": {
"express": "^5.1.0",
"body-parser": "^2.2.0"
"body-parser": "^2.2.0",
"dotenv": "^16.4.5",
"express-validator": "^7.2.0",
"express-rate-limit": "^7.4.1",
"winston": "^3.15.0"
}
}

View File

@ -1,11 +1,17 @@
// Пример файла с роутами
// Пример файла с роутами с валидацией
// Используйте эту структуру для организации API endpoints
const express = require('express');
const { body, param } = require('express-validator');
const validate = require('../middleware/validate');
const { strictLimiter } = require('../middleware/rateLimiter');
const logger = require('../config/logger');
const router = express.Router();
// GET endpoint
router.get('/hello', (req, res) => {
logger.info('Hello endpoint called');
res.json({
success: true,
message: 'Hello from example route!',
@ -13,34 +19,70 @@ router.get('/hello', (req, res) => {
});
// POST endpoint с валидацией
router.post('/data', (req, res) => {
router.post(
'/data',
strictLimiter, // Применить строгий rate limiter
[
body('name')
.trim()
.notEmpty()
.withMessage('Name is required')
.isLength({ min: 2, max: 50 })
.withMessage('Name must be between 2 and 50 characters'),
body('value')
.notEmpty()
.withMessage('Value is required')
.isNumeric()
.withMessage('Value must be a number'),
],
validate, // Middleware для обработки ошибок валидации
(req, res) => {
try {
const { name, value } = req.body;
// Простая валидация
if (!name || !value) {
return res.status(400).json({
success: false,
error: 'Name and value are required',
});
}
logger.info(`Processing data: name=${name}, value=${value}`);
// Обработка данных
res.json({
success: true,
data: {
name,
value,
value: Number(value),
processed: true,
timestamp: new Date().toISOString(),
},
});
} catch (err) {
logger.error('Error processing data:', err);
res.status(500).json({
success: false,
error: err.message,
});
}
});
}
);
// GET с параметром и валидацией
router.get(
'/item/:id',
[
param('id')
.isInt({ min: 1 })
.withMessage('ID must be a positive integer'),
],
validate,
(req, res) => {
const { id } = req.params;
logger.info(`Getting item with id: ${id}`);
res.json({
success: true,
data: {
id: Number(id),
name: 'Example Item',
},
});
}
);
module.exports = router;

View File

@ -1,13 +1,19 @@
// Загрузка переменных окружения
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const logger = require('./middleware/logger');
const winstonLogger = require('./config/logger');
const simpleLogger = require('./middleware/logger'); // Простое логирование для разработки
const errorHandler = require('./middleware/errorHandler');
const { generalLimiter } = require('./middleware/rateLimiter');
const app = express();
const PORT = process.env.PORT || 3001;
// Middleware
app.use(logger);
app.use(simpleLogger); // Простое логирование запросов
app.use(generalLimiter); // Rate limiting
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
@ -42,9 +48,9 @@ app.post('/api/example', (req, res) => {
}
});
// Подключение роутов (пример)
// const exampleRoutes = require('./routes/example');
// app.use('/api/example', exampleRoutes);
// Подключение роутов
const exampleRoutes = require('./routes/example');
app.use('/api/example', exampleRoutes);
// Обработка 404
app.use((req, res) => {
@ -59,7 +65,8 @@ app.use(errorHandler);
// Запуск сервера
app.listen(PORT, () => {
console.log(`🚀 Server is running on http://localhost:${PORT}`);
console.log(`📡 Health check: http://localhost:${PORT}/api/health`);
winstonLogger.info(`🚀 Server is running on http://localhost:${PORT}`);
winstonLogger.info(`📡 Health check: http://localhost:${PORT}/api/health`);
winstonLogger.info(`📝 Environment: ${process.env.NODE_ENV || 'development'}`);
});

33
docker-compose.yml Normal file
View File

@ -0,0 +1,33 @@
# Docker Compose конфигурация для разработки
version: '3.8'
services:
backend:
build:
context: .
dockerfile: Dockerfile
ports:
- "3001:3001"
environment:
- NODE_ENV=development
- PORT=3001
volumes:
- ./backend:/app
- /app/node_modules
env_file:
- ./backend/.env
frontend:
build:
context: .
dockerfile: Dockerfile.frontend
ports:
- "3000:3000"
depends_on:
- backend
# Для использования:
# docker-compose up -d # Запустить в фоне
# docker-compose logs -f # Просмотр логов
# docker-compose down # Остановить

94
docs/QUICK_START.md Normal file
View File

@ -0,0 +1,94 @@
# Быстрый старт с улучшениями
## 🚀 Установка всех зависимостей
```powershell
# Frontend
cd frontend
npm install
# Backend
cd ../backend
npm install
```
## ⚙️ Настройка переменных окружения
```powershell
# Frontend
cd frontend
Copy-Item .env.example .env.local
# Отредактируйте .env.local при необходимости
# Backend
cd ../backend
Copy-Item .env.example .env
# Отредактируйте .env при необходимости
```
## 🏃 Запуск в разработке
### Обычный способ (без Docker):
```powershell
# Терминал 1 - Backend
cd backend
node server.js
# Терминал 2 - Frontend
cd frontend
npm run dev
```
### С Docker:
```powershell
docker-compose up -d
```
## 📝 Форматирование кода
```powershell
cd frontend
npm run format # Форматировать весь код
npm run format:check # Проверить форматирование
```
## 🧪 Проверка работы
1. **Backend**: Откройте http://localhost:3001/api/health
2. **Frontend**: Откройте http://localhost:3000
3. **Пример API**: Попробуйте POST на http://localhost:3001/api/example/data
### Тестовый запрос:
```powershell
# PowerShell
Invoke-RestMethod -Uri "http://localhost:3001/api/example/data" -Method POST -ContentType "application/json" -Body '{"name":"Test","value":123}'
```
## 📊 Просмотр логов
Backend логи находятся в `backend/logs/`:
- `error.log` - ошибки
- `combined.log` - все логи
В консоли также выводятся логи (в режиме разработки).
## ✅ Чеклист перед деплоем
- [ ] Все зависимости установлены
- [ ] `.env` файлы настроены
- [ ] Линтер проходит без ошибок (`npm run lint`)
- [ ] Форматирование проверено (`npm run format:check`)
- [ ] Production build собирается (`npm run build`)
- [ ] Логи работают корректно
- [ ] Rate limiting настроен (если нужно)
- [ ] Валидация работает на всех endpoints
## 🔍 Дополнительная информация
- Подробное руководство: [`docs/USAGE_GUIDE.md`](USAGE_GUIDE.md)
- Правила проекта: [`docs/PROJECT_RULES.md`](PROJECT_RULES.md)
- База знаний: [`docs/KNOWLEDGE_BASE.md`](KNOWLEDGE_BASE.md)

269
docs/USAGE_GUIDE.md Normal file
View File

@ -0,0 +1,269 @@
# Руководство по использованию улучшений шаблона
## 📋 Содержание
1. [Переменные окружения](#переменные-окружения)
2. [Логирование](#логирование)
3. [Валидация запросов](#валидация-запросов)
4. [Rate Limiting](#rate-limiting)
5. [Docker](#docker)
6. [CI/CD](#cicd)
## 🔐 Переменные окружения
### Установка dotenv
```powershell
cd backend
npm install
```
### Использование
1. Скопируйте `.env.example` в `.env`:
```powershell
Copy-Item backend\.env.example backend\.env
```
2. Заполните значения в `backend/.env`
3. Переменные автоматически загружаются при старте сервера
### Доступные переменные
- `PORT` - порт сервера (по умолчанию 3001)
- `NODE_ENV` - окружение (development/production)
- `LOG_LEVEL` - уровень логирования (error/warn/info/debug)
## 📝 Логирование
### Winston
Winston настроен для логирования в файлы и консоль.
### Логи создаются в `backend/logs/`:
- `error.log` - только ошибки
- `combined.log` - все логи
### Использование в коде:
```javascript
const logger = require('./config/logger');
// Разные уровни логирования
logger.error('Error message');
logger.warn('Warning message');
logger.info('Info message');
logger.debug('Debug message');
// С контекстом
logger.info('User login', { userId: 123, ip: '192.168.1.1' });
```
### Настройка уровня логирования
В `.env` файле:
```
LOG_LEVEL=debug # error, warn, info, debug
```
## ✅ Валидация запросов
### Express-Validator
Используется для валидации входящих данных.
### Пример использования:
```javascript
const { body } = require('express-validator');
const validate = require('../middleware/validate');
router.post(
'/endpoint',
[
body('email')
.isEmail()
.withMessage('Invalid email'),
body('password')
.isLength({ min: 8 })
.withMessage('Password must be at least 8 characters'),
],
validate,
(req, res) => {
// Валидация прошла успешно
// req.body содержит проверенные данные
}
);
```
### Доступные валидаторы:
- `body()` - валидация тела запроса
- `param()` - валидация параметров URL
- `query()` - валидация query параметров
### Популярные методы:
```javascript
body('field')
.notEmpty() // Не пустое
.isEmail() // Email формат
.isLength({ min: 5 }) // Минимальная длина
.isInt() // Целое число
.isFloat() // Число с плавающей точкой
.trim() // Убрать пробелы
.custom((value) => { // Кастомная валидация
// Ваша логика
return true;
})
```
## 🛡️ Rate Limiting
### Защита от злоупотреблений
Два уровня защиты настроены:
1. **Общий limiter** (`generalLimiter`):
- 100 запросов за 15 минут
- Применяется ко всем маршрутам
2. **Строгий limiter** (`strictLimiter`):
- 20 запросов за 15 минут
- Для важных endpoints
### Использование:
```javascript
const { strictLimiter } = require('../middleware/rateLimiter');
router.post('/api/sensitive', strictLimiter, (req, res) => {
// Защищенный endpoint
});
```
### Настройка:
В `.env` (опционально):
```
RATE_LIMIT_WINDOW_MS=900000 # 15 минут в миллисекундах
RATE_LIMIT_MAX_REQUESTS=100 # Максимум запросов
```
## 🐳 Docker
### Установка Docker
Убедитесь, что Docker установлен на вашей системе.
### Структура:
- `Dockerfile` - для backend
- `Dockerfile.frontend` - для frontend
- `docker-compose.yml` - для разработки
### Использование Docker Compose:
```powershell
# Запустить все сервисы
docker-compose up -d
# Просмотр логов
docker-compose logs -f
# Остановить
docker-compose down
# Пересобрать
docker-compose up -d --build
```
### Отдельная сборка:
```powershell
# Backend
docker build -t my-app-backend -f Dockerfile .
docker run -p 3001:3001 my-app-backend
# Frontend
docker build -t my-app-frontend -f Dockerfile.frontend .
docker run -p 3000:3000 my-app-frontend
```
### Переменные окружения в Docker:
Создайте `.env` файл или используйте `env_file` в `docker-compose.yml`.
## 🔄 CI/CD
### GitHub Actions
Автоматическая проверка кода при push в репозиторий.
### Что проверяется:
- ✅ Установка зависимостей
- ✅ ESLint проверка
- ✅ Prettier форматирование
- ✅ Сборка frontend
- ✅ Проверка синтаксиса backend
### Файл: `.github/workflows/ci.yml`
Workflow автоматически запускается при:
- Push в ветки `main` или `dev`
- Pull Request в `main`
### Просмотр результатов:
В GitHub репозитории: **Actions** → выберите workflow run
## 🔧 Интеграция всех улучшений
### Пример полного endpoint:
```javascript
const express = require('express');
const { body } = require('express-validator');
const validate = require('../middleware/validate');
const { strictLimiter } = require('../middleware/rateLimiter');
const logger = require('../config/logger');
router.post(
'/api/users',
strictLimiter,
[
body('name')
.trim()
.notEmpty()
.withMessage('Name is required'),
body('email')
.isEmail()
.withMessage('Invalid email'),
],
validate,
async (req, res) => {
try {
logger.info('Creating user', { email: req.body.email });
// Ваша логика
const user = { /* ... */ };
logger.info('User created successfully', { userId: user.id });
res.json({ success: true, data: user });
} catch (err) {
logger.error('Error creating user', { error: err.message });
res.status(500).json({ success: false, error: err.message });
}
}
);
```
## 📚 Дополнительные ресурсы
- [Express Validator документация](https://express-validator.github.io/docs/)
- [Winston документация](https://github.com/winstonjs/winston)
- [Express Rate Limit](https://github.com/express-rate-limit/express-rate-limit)
- [Docker документация](https://docs.docker.com/)