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
Some checks are pending
CI/CD / lint-and-build (push) Waiting to run
This commit is contained in:
parent
da1de34d21
commit
77e30fdaa4
48
.github/workflows/ci.yml
vendored
Normal file
48
.github/workflows/ci.yml
vendored
Normal 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
7
.gitignore
vendored
@ -47,3 +47,10 @@ next-env.d.ts
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
|||||||
21
Dockerfile
Normal file
21
Dockerfile
Normal 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
30
Dockerfile.frontend
Normal 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"]
|
||||||
|
|
||||||
100
IMPROVEMENTS.md
100
IMPROVEMENTS.md
@ -1,6 +1,6 @@
|
|||||||
# Рекомендации по улучшению шаблона
|
# Рекомендации по улучшению шаблона
|
||||||
|
|
||||||
## Добавленные улучшения
|
## ✅ Реализованные улучшения
|
||||||
|
|
||||||
### 1. Prettier для форматирования кода
|
### 1. Prettier для форматирования кода
|
||||||
- Конфигурация `.prettierrc`
|
- Конфигурация `.prettierrc`
|
||||||
@ -13,77 +13,81 @@ npm run format # Форматировать весь код
|
|||||||
npm run format:check # Проверить форматирование
|
npm run format:check # Проверить форматирование
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Переменные окружения
|
### 2. Переменные окружения (dotenv)
|
||||||
- `.env.example` файлы для frontend и backend
|
- `.env.example` файлы для frontend и backend
|
||||||
|
- Автоматическая загрузка через `dotenv`
|
||||||
- Шаблоны для быстрого старта
|
- Шаблоны для быстрого старта
|
||||||
- Документация в файлах
|
|
||||||
|
|
||||||
### 3. Middleware для бэкенда
|
### 3. Middleware для бэкенда
|
||||||
- `logger.js` - логирование всех запросов
|
- `logger.js` - простое логирование всех запросов
|
||||||
- `errorHandler.js` - централизованная обработка ошибок
|
- `errorHandler.js` - централизованная обработка ошибок
|
||||||
- Пример использования в `server.js`
|
- Интегрировано в `server.js`
|
||||||
|
|
||||||
### 4. Структура роутов
|
### 4. Продвинутое логирование (Winston)
|
||||||
- Пример файла `routes/example.js`
|
- Структурированные логи в файлы
|
||||||
|
- Разные уровни логирования
|
||||||
|
- Логи в `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 по модулям
|
- Организация API endpoints по модулям
|
||||||
- Готовый шаблон для новых роутов
|
- Готовый шаблон для новых роутов
|
||||||
|
|
||||||
### 5. Пример компонента
|
### 8. Пример компонента
|
||||||
- `ExampleComponent.tsx` с использованием API
|
- `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
|
- [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) - Подробное руководство по всем улучшениям
|
||||||
npm install winston
|
- [`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)
|
Все улучшения готовы к использованию. См. [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) для подробных инструкций по каждому улучшению.
|
||||||
```bash
|
|
||||||
npm install express-rate-limit
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **TypeScript для бэкенда**
|
## 🔮 Дополнительные возможности (опционально)
|
||||||
|
|
||||||
|
1. **TypeScript для бэкенда**
|
||||||
- Переименовать `.js` в `.ts`
|
- Переименовать `.js` в `.ts`
|
||||||
- Настроить `tsconfig.json` для backend
|
- Настроить `tsconfig.json` для backend
|
||||||
- Добавить типы для Express
|
- Добавить типы для Express
|
||||||
|
|
||||||
6. **Docker поддержка** (опционально)
|
2. **Тестирование**
|
||||||
- `Dockerfile` для frontend и backend
|
|
||||||
- `docker-compose.yml`
|
|
||||||
|
|
||||||
7. **Тестирование** (опционально)
|
|
||||||
- Jest для unit тестов
|
- Jest для unit тестов
|
||||||
- Testing Library для компонентов
|
- Testing Library для компонентов
|
||||||
|
|
||||||
8. **CI/CD** (GitHub Actions)
|
3. **База данных**
|
||||||
- Автоматическая проверка кода
|
- Подключение к PostgreSQL/MySQL
|
||||||
- Автоматический деплой
|
- ORM (Prisma, Sequelize)
|
||||||
|
|
||||||
## Текущая структура
|
|
||||||
|
|
||||||
Все основные улучшения уже добавлены:
|
|
||||||
- ✅ Prettier
|
|
||||||
- ✅ Environment variables examples
|
|
||||||
- ✅ Middleware структура
|
|
||||||
- ✅ Примеры роутов
|
|
||||||
- ✅ Пример компонента
|
|
||||||
- ✅ Логирование
|
|
||||||
- ✅ Обработка ошибок
|
|
||||||
|
|
||||||
Шаблон готов к использованию и может быть расширен по мере необходимости.
|
|
||||||
|
|
||||||
|
4. **Аутентификация**
|
||||||
|
- JWT токены
|
||||||
|
- Passport.js стратегии
|
||||||
|
|||||||
13
README.md
13
README.md
@ -152,6 +152,19 @@ npm run format:check # Проверить форматирование
|
|||||||
- `frontend/.env.example` → `frontend/.env.local`
|
- `frontend/.env.example` → `frontend/.env.local`
|
||||||
- `backend/.env.example` → `backend/.env`
|
- `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
|
ISC
|
||||||
|
|||||||
40
backend/config/logger.js
Normal file
40
backend/config/logger.js
Normal 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;
|
||||||
|
|
||||||
31
backend/middleware/rateLimiter.js
Normal file
31
backend/middleware/rateLimiter.js
Normal 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,
|
||||||
|
};
|
||||||
|
|
||||||
24
backend/middleware/validate.js
Normal file
24
backend/middleware/validate.js
Normal 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;
|
||||||
|
|
||||||
@ -13,7 +13,11 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^5.1.0",
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
// Пример файла с роутами
|
// Пример файла с роутами с валидацией
|
||||||
// Используйте эту структуру для организации API endpoints
|
// Используйте эту структуру для организации API endpoints
|
||||||
|
|
||||||
const express = require('express');
|
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();
|
const router = express.Router();
|
||||||
|
|
||||||
// GET endpoint
|
// GET endpoint
|
||||||
router.get('/hello', (req, res) => {
|
router.get('/hello', (req, res) => {
|
||||||
|
logger.info('Hello endpoint called');
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: 'Hello from example route!',
|
message: 'Hello from example route!',
|
||||||
@ -13,34 +19,70 @@ router.get('/hello', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// POST endpoint с валидацией
|
// POST endpoint с валидацией
|
||||||
router.post('/data', (req, res) => {
|
router.post(
|
||||||
try {
|
'/data',
|
||||||
const { name, value } = req.body;
|
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;
|
||||||
|
|
||||||
// Простая валидация
|
logger.info(`Processing data: name=${name}, value=${value}`);
|
||||||
if (!name || !value) {
|
|
||||||
return res.status(400).json({
|
// Обработка данных
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
value: Number(value),
|
||||||
|
processed: true,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('Error processing data:', err);
|
||||||
|
res.status(500).json({
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Name and value are required',
|
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({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
data: {
|
data: {
|
||||||
name,
|
id: Number(id),
|
||||||
value,
|
name: 'Example Item',
|
||||||
processed: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (err) {
|
|
||||||
res.status(500).json({
|
|
||||||
success: false,
|
|
||||||
error: err.message,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
|
// Загрузка переменных окружения
|
||||||
|
require('dotenv').config();
|
||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const bodyParser = require('body-parser');
|
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 errorHandler = require('./middleware/errorHandler');
|
||||||
|
const { generalLimiter } = require('./middleware/rateLimiter');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3001;
|
const PORT = process.env.PORT || 3001;
|
||||||
|
|
||||||
// Middleware
|
// Middleware
|
||||||
app.use(logger);
|
app.use(simpleLogger); // Простое логирование запросов
|
||||||
|
app.use(generalLimiter); // Rate limiting
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
@ -42,9 +48,9 @@ app.post('/api/example', (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Подключение роутов (пример)
|
// Подключение роутов
|
||||||
// const exampleRoutes = require('./routes/example');
|
const exampleRoutes = require('./routes/example');
|
||||||
// app.use('/api/example', exampleRoutes);
|
app.use('/api/example', exampleRoutes);
|
||||||
|
|
||||||
// Обработка 404
|
// Обработка 404
|
||||||
app.use((req, res) => {
|
app.use((req, res) => {
|
||||||
@ -59,7 +65,8 @@ app.use(errorHandler);
|
|||||||
|
|
||||||
// Запуск сервера
|
// Запуск сервера
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
winstonLogger.info(`🚀 Server is running on http://localhost:${PORT}`);
|
||||||
console.log(`📡 Health check: http://localhost:${PORT}/api/health`);
|
winstonLogger.info(`📡 Health check: http://localhost:${PORT}/api/health`);
|
||||||
|
winstonLogger.info(`📝 Environment: ${process.env.NODE_ENV || 'development'}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
33
docker-compose.yml
Normal file
33
docker-compose.yml
Normal 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
94
docs/QUICK_START.md
Normal 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
269
docs/USAGE_GUIDE.md
Normal 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/)
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user