feat: Add improvements - Prettier, env examples, middleware, examples

This commit is contained in:
DosAi 2025-11-02 16:43:28 +03:00
parent 981d5eb71e
commit da1de34d21
12 changed files with 326 additions and 4 deletions

8
.prettierignore Normal file
View File

@ -0,0 +1,8 @@
node_modules
.next
out
dist
build
*.log
.env*

11
.prettierrc Normal file
View File

@ -0,0 +1,11 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": false,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"arrowParens": "always",
"endOfLine": "lf"
}

89
IMPROVEMENTS.md Normal file
View File

@ -0,0 +1,89 @@
# Рекомендации по улучшению шаблона
## Добавленные улучшения
### 1. Prettier для форматирования кода
- Конфигурация `.prettierrc`
- Игнорирование файлов `.prettierignore`
- Скрипты в package.json для форматирования
**Использование:**
```powershell
npm run format # Форматировать весь код
npm run format:check # Проверить форматирование
```
### 2. Переменные окружения
- `.env.example` файлы для frontend и backend
- Шаблоны для быстрого старта
- Документация в файлах
### 3. Middleware для бэкенда
- `logger.js` - логирование всех запросов
- `errorHandler.js` - централизованная обработка ошибок
- Пример использования в `server.js`
### 4. Структура роутов
- Пример файла `routes/example.js`
- Организация API endpoints по модулям
- Готовый шаблон для новых роутов
### 5. Пример компонента
- `ExampleComponent.tsx` с использованием API
- Демонстрация работы с состоянием
- Обработка ошибок и загрузки
## Дополнительные рекомендации
### Можно добавить в будущем:
1. **Валидация запросов** (express-validator)
```bash
npm install express-validator
```
2. **Логирование** (winston или pino)
```bash
npm install winston
```
3. **Валидация окружения** (dotenv-safe)
```bash
npm install dotenv-safe
```
4. **Rate limiting** (express-rate-limit)
```bash
npm install express-rate-limit
```
5. **TypeScript для бэкенда**
- Переименовать `.js` в `.ts`
- Настроить `tsconfig.json` для backend
- Добавить типы для Express
6. **Docker поддержка** (опционально)
- `Dockerfile` для frontend и backend
- `docker-compose.yml`
7. **Тестирование** (опционально)
- Jest для unit тестов
- Testing Library для компонентов
8. **CI/CD** (GitHub Actions)
- Автоматическая проверка кода
- Автоматический деплой
## Текущая структура
Все основные улучшения уже добавлены:
- ✅ Prettier
- ✅ Environment variables examples
- ✅ Middleware структура
- ✅ Примеры роутов
- ✅ Пример компонента
- ✅ Логирование
- ✅ Обработка ошибок
Шаблон готов к использованию и может быть расширен по мере необходимости.

View File

@ -136,6 +136,22 @@ pm2 start frontend/.next/start.js --name my-project-frontend
Подробнее: [`docs/PROJECT_RULES.md`](docs/PROJECT_RULES.md)
## 🔧 Дополнительные инструменты
### Форматирование кода (Prettier)
```powershell
cd frontend
npm run format # Форматировать весь код
npm run format:check # Проверить форматирование
```
### Переменные окружения
Скопируйте `.env.example` файлы и заполните значения:
- `frontend/.env.example``frontend/.env.local`
- `backend/.env.example``backend/.env`
## 📝 Лицензия
ISC
@ -144,3 +160,7 @@ ISC
Создано на основе стандартов разработки DosAi
## 📚 Дополнительная информация
См. [`IMPROVEMENTS.md`](IMPROVEMENTS.md) для списка улучшений и рекомендаций.

View File

@ -0,0 +1,10 @@
# Middleware
Размещайте здесь middleware функции для Express.
Примеры:
- logger.js - логирование запросов
- errorHandler.js - обработка ошибок
- auth.js - аутентификация (если нужно)
- validate.js - валидация запросов (если нужно)

View File

@ -0,0 +1,16 @@
// Middleware для обработки ошибок
const errorHandler = (err, req, res, next) => {
console.error('Error:', err);
const statusCode = err.statusCode || 500;
const message = err.message || 'Internal Server Error';
res.status(statusCode).json({
success: false,
error: message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
});
};
module.exports = errorHandler;

View File

@ -0,0 +1,21 @@
// Middleware для логирования запросов
const logger = (req, res, next) => {
const timestamp = new Date().toISOString();
const method = req.method;
const url = req.url;
const ip = req.ip || req.connection.remoteAddress;
console.log(`[${timestamp}] ${method} ${url} - ${ip}`);
// Логируем время ответа
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`[${timestamp}] ${method} ${url} - ${res.statusCode} (${duration}ms)`);
});
next();
};
module.exports = logger;

46
backend/routes/example.js Normal file
View File

@ -0,0 +1,46 @@
// Пример файла с роутами
// Используйте эту структуру для организации API endpoints
const express = require('express');
const router = express.Router();
// GET endpoint
router.get('/hello', (req, res) => {
res.json({
success: true,
message: 'Hello from example route!',
});
});
// POST endpoint с валидацией
router.post('/data', (req, res) => {
try {
const { name, value } = req.body;
// Простая валидация
if (!name || !value) {
return res.status(400).json({
success: false,
error: 'Name and value are required',
});
}
// Обработка данных
res.json({
success: true,
data: {
name,
value,
processed: true,
},
});
} catch (err) {
res.status(500).json({
success: false,
error: err.message,
});
}
});
module.exports = router;

View File

@ -1,10 +1,13 @@
const express = require('express');
const bodyParser = require('body-parser');
const logger = require('./middleware/logger');
const errorHandler = require('./middleware/errorHandler');
const app = express();
const PORT = process.env.PORT || 3001;
// Middleware
app.use(logger);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
@ -20,9 +23,13 @@ app.use((req, res, next) => {
}
});
// Тестовый endpoint
// Health check endpoint
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', message: 'Server is running' });
res.json({
status: 'ok',
message: 'Server is running',
timestamp: new Date().toISOString(),
});
});
// Пример API endpoint
@ -35,6 +42,21 @@ app.post('/api/example', (req, res) => {
}
});
// Подключение роутов (пример)
// const exampleRoutes = require('./routes/example');
// app.use('/api/example', exampleRoutes);
// Обработка 404
app.use((req, res) => {
res.status(404).json({
success: false,
error: 'Route not found',
});
});
// Обработка ошибок (должен быть последним middleware)
app.use(errorHandler);
// Запуск сервера
app.listen(PORT, () => {
console.log(`🚀 Server is running on http://localhost:${PORT}`);

View File

@ -1,3 +1,5 @@
import ExampleComponent from '@/components/ExampleComponent';
export default function Home() {
return (
<div className="min-h-screen py-8">
@ -17,6 +19,10 @@ export default function Home() {
<li>Начните разработку!</li>
</ul>
</div>
<div className="mt-8">
<ExampleComponent />
</div>
</div>
</div>
);

View File

@ -0,0 +1,70 @@
// Пример React компонента с использованием API
'use client';
import { useState } from 'react';
import { apiRequest } from '@/lib/api';
interface ApiData {
name: string;
value: string;
}
export default function ExampleComponent() {
const [data, setData] = useState<ApiData | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleFetch = async () => {
setLoading(true);
setError(null);
try {
const response = await apiRequest<ApiData>('example', {
method: 'POST',
body: JSON.stringify({
name: 'Test',
value: '123',
}),
});
if (response.success && response.data) {
setData(response.data);
} else {
setError(response.error || 'Unknown error');
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to fetch data');
} finally {
setLoading(false);
}
};
return (
<div className="p-4 bg-gray-700 rounded-lg">
<h2 className="text-xl font-semibold mb-4">Пример компонента</h2>
<button
onClick={handleFetch}
disabled={loading}
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 rounded"
>
{loading ? 'Загрузка...' : 'Получить данные'}
</button>
{error && (
<div className="mt-4 p-2 bg-red-800 text-red-200 rounded">
Ошибка: {error}
</div>
)}
{data && (
<div className="mt-4 p-2 bg-green-800 text-green-200 rounded">
<p>Name: {data.name}</p>
<p>Value: {data.value}</p>
</div>
)}
</div>
);
}

View File

@ -6,7 +6,9 @@
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
"lint": "next lint",
"format": "prettier --write .",
"format:check": "prettier --check ."
},
"dependencies": {
"react": "^19.0.0",
@ -22,7 +24,8 @@
"tailwindcss": "^4",
"eslint": "^9",
"eslint-config-next": "15.3.3",
"@eslint/eslintrc": "^3"
"@eslint/eslintrc": "^3",
"prettier": "^3"
}
}