Compare commits
No commits in common. "6c264726603f40bec830a90a64faa5ee44df820a" and "4515b68ad1de3e1d6741e4e09671c0529bacdb67" have entirely different histories.
6c26472660
...
4515b68ad1
48
.github/workflows/ci.yml
vendored
48
.github/workflows/ci.yml
vendored
@ -1,48 +0,0 @@
|
|||||||
# 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,10 +47,3 @@ next-env.d.ts
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Logs
|
|
||||||
logs/
|
|
||||||
*.log
|
|
||||||
|
|
||||||
# Docker
|
|
||||||
.dockerignore
|
|
||||||
|
|
||||||
|
|||||||
21
Dockerfile
21
Dockerfile
@ -1,21 +0,0 @@
|
|||||||
# 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"]
|
|
||||||
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
# 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,81 +13,77 @@ npm run format # Форматировать весь код
|
|||||||
npm run format:check # Проверить форматирование
|
npm run format:check # Проверить форматирование
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Переменные окружения (dotenv)
|
### 2. Переменные окружения
|
||||||
- `.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. Продвинутое логирование (Winston)
|
### 4. Структура роутов
|
||||||
- Структурированные логи в файлы
|
- Пример файла `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 по модулям
|
||||||
- Готовый шаблон для новых роутов
|
- Готовый шаблон для новых роутов
|
||||||
|
|
||||||
### 8. Пример компонента
|
### 5. Пример компонента
|
||||||
- `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)
|
||||||
- [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) - Подробное руководство по всем улучшениям
|
```bash
|
||||||
- [`docs/QUICK_START.md`](docs/QUICK_START.md) - Быстрый старт
|
npm install winston
|
||||||
- [`docs/PROJECT_RULES.md`](docs/PROJECT_RULES.md) - Правила разработки
|
```
|
||||||
- [`docs/KNOWLEDGE_BASE.md`](docs/KNOWLEDGE_BASE.md) - База знаний
|
|
||||||
|
|
||||||
## 🎯 Использование улучшений
|
3. **Валидация окружения** (dotenv-safe)
|
||||||
|
```bash
|
||||||
|
npm install dotenv-safe
|
||||||
|
```
|
||||||
|
|
||||||
Все улучшения готовы к использованию. См. [`docs/USAGE_GUIDE.md`](docs/USAGE_GUIDE.md) для подробных инструкций по каждому улучшению.
|
4. **Rate limiting** (express-rate-limit)
|
||||||
|
```bash
|
||||||
|
npm install express-rate-limit
|
||||||
|
```
|
||||||
|
|
||||||
## 🔮 Дополнительные возможности (опционально)
|
5. **TypeScript для бэкенда**
|
||||||
|
|
||||||
1. **TypeScript для бэкенда**
|
|
||||||
- Переименовать `.js` в `.ts`
|
- Переименовать `.js` в `.ts`
|
||||||
- Настроить `tsconfig.json` для backend
|
- Настроить `tsconfig.json` для backend
|
||||||
- Добавить типы для Express
|
- Добавить типы для Express
|
||||||
|
|
||||||
2. **Тестирование**
|
6. **Docker поддержка** (опционально)
|
||||||
|
- `Dockerfile` для frontend и backend
|
||||||
|
- `docker-compose.yml`
|
||||||
|
|
||||||
|
7. **Тестирование** (опционально)
|
||||||
- Jest для unit тестов
|
- Jest для unit тестов
|
||||||
- Testing Library для компонентов
|
- Testing Library для компонентов
|
||||||
|
|
||||||
3. **База данных**
|
8. **CI/CD** (GitHub Actions)
|
||||||
- Подключение к PostgreSQL/MySQL
|
- Автоматическая проверка кода
|
||||||
- ORM (Prisma, Sequelize)
|
- Автоматический деплой
|
||||||
|
|
||||||
|
## Текущая структура
|
||||||
|
|
||||||
|
Все основные улучшения уже добавлены:
|
||||||
|
- ✅ Prettier
|
||||||
|
- ✅ Environment variables examples
|
||||||
|
- ✅ Middleware структура
|
||||||
|
- ✅ Примеры роутов
|
||||||
|
- ✅ Пример компонента
|
||||||
|
- ✅ Логирование
|
||||||
|
- ✅ Обработка ошибок
|
||||||
|
|
||||||
|
Шаблон готов к использованию и может быть расширен по мере необходимости.
|
||||||
|
|
||||||
4. **Аутентификация**
|
|
||||||
- JWT токены
|
|
||||||
- Passport.js стратегии
|
|
||||||
|
|||||||
13
README.md
13
README.md
@ -152,19 +152,6 @@ 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
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
// Конфигурация 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;
|
|
||||||
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
// 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
// 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,11 +13,7 @@
|
|||||||
"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,17 +1,11 @@
|
|||||||
// Пример файла с роутами с валидацией
|
// Пример файла с роутами
|
||||||
// Используйте эту структуру для организации 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!',
|
||||||
@ -19,70 +13,34 @@ router.get('/hello', (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// POST endpoint с валидацией
|
// POST endpoint с валидацией
|
||||||
router.post(
|
router.post('/data', (req, res) => {
|
||||||
'/data',
|
try {
|
||||||
strictLimiter, // Применить строгий rate limiter
|
const { name, value } = req.body;
|
||||||
[
|
|
||||||
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: err.message,
|
error: 'Name and value are required',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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: {
|
||||||
id: Number(id),
|
name,
|
||||||
name: 'Example Item',
|
value,
|
||||||
|
processed: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: err.message,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,13 @@
|
|||||||
// Загрузка переменных окружения
|
|
||||||
require('dotenv').config();
|
|
||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const winstonLogger = require('./config/logger');
|
const logger = require('./middleware/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(simpleLogger); // Простое логирование запросов
|
app.use(logger);
|
||||||
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 }));
|
||||||
|
|
||||||
@ -48,9 +42,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) => {
|
||||||
@ -65,8 +59,7 @@ app.use(errorHandler);
|
|||||||
|
|
||||||
// Запуск сервера
|
// Запуск сервера
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
winstonLogger.info(`🚀 Server is running on http://localhost:${PORT}`);
|
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
||||||
winstonLogger.info(`📡 Health check: http://localhost:${PORT}/api/health`);
|
console.log(`📡 Health check: http://localhost:${PORT}/api/health`);
|
||||||
winstonLogger.info(`📝 Environment: ${process.env.NODE_ENV || 'development'}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
# 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 # Остановить
|
|
||||||
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
# Быстрый старт с улучшениями
|
|
||||||
|
|
||||||
## 🚀 Установка всех зависимостей
|
|
||||||
|
|
||||||
```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)
|
|
||||||
|
|
||||||
@ -1,269 +0,0 @@
|
|||||||
# Руководство по использованию улучшений шаблона
|
|
||||||
|
|
||||||
## 📋 Содержание
|
|
||||||
|
|
||||||
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