Compare commits
No commits in common. "4515b68ad1de3e1d6741e4e09671c0529bacdb67" and "981d5eb71e175dfb78470133201c504e29b7654f" have entirely different histories.
4515b68ad1
...
981d5eb71e
@ -1,8 +0,0 @@
|
|||||||
node_modules
|
|
||||||
.next
|
|
||||||
out
|
|
||||||
dist
|
|
||||||
build
|
|
||||||
*.log
|
|
||||||
.env*
|
|
||||||
|
|
||||||
11
.prettierrc
11
.prettierrc
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"semi": true,
|
|
||||||
"trailingComma": "es5",
|
|
||||||
"singleQuote": false,
|
|
||||||
"printWidth": 80,
|
|
||||||
"tabWidth": 2,
|
|
||||||
"useTabs": false,
|
|
||||||
"arrowParens": "always",
|
|
||||||
"endOfLine": "lf"
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
# Рекомендации по улучшению шаблона
|
|
||||||
|
|
||||||
## Добавленные улучшения
|
|
||||||
|
|
||||||
### 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 структура
|
|
||||||
- ✅ Примеры роутов
|
|
||||||
- ✅ Пример компонента
|
|
||||||
- ✅ Логирование
|
|
||||||
- ✅ Обработка ошибок
|
|
||||||
|
|
||||||
Шаблон готов к использованию и может быть расширен по мере необходимости.
|
|
||||||
|
|
||||||
20
README.md
20
README.md
@ -136,22 +136,6 @@ pm2 start frontend/.next/start.js --name my-project-frontend
|
|||||||
|
|
||||||
Подробнее: [`docs/PROJECT_RULES.md`](docs/PROJECT_RULES.md)
|
Подробнее: [`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
|
ISC
|
||||||
@ -160,7 +144,3 @@ ISC
|
|||||||
|
|
||||||
Создано на основе стандартов разработки DosAi
|
Создано на основе стандартов разработки DosAi
|
||||||
|
|
||||||
## 📚 Дополнительная информация
|
|
||||||
|
|
||||||
См. [`IMPROVEMENTS.md`](IMPROVEMENTS.md) для списка улучшений и рекомендаций.
|
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
# Middleware
|
|
||||||
|
|
||||||
Размещайте здесь middleware функции для Express.
|
|
||||||
|
|
||||||
Примеры:
|
|
||||||
- logger.js - логирование запросов
|
|
||||||
- errorHandler.js - обработка ошибок
|
|
||||||
- auth.js - аутентификация (если нужно)
|
|
||||||
- validate.js - валидация запросов (если нужно)
|
|
||||||
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
// Пример файла с роутами
|
|
||||||
// Используйте эту структуру для организации 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;
|
|
||||||
|
|
||||||
@ -1,13 +1,10 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const logger = require('./middleware/logger');
|
|
||||||
const errorHandler = require('./middleware/errorHandler');
|
|
||||||
|
|
||||||
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(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
@ -23,13 +20,9 @@ app.use((req, res, next) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Health check endpoint
|
// Тестовый endpoint
|
||||||
app.get('/api/health', (req, res) => {
|
app.get('/api/health', (req, res) => {
|
||||||
res.json({
|
res.json({ status: 'ok', message: 'Server is running' });
|
||||||
status: 'ok',
|
|
||||||
message: 'Server is running',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Пример API endpoint
|
// Пример API endpoint
|
||||||
@ -42,21 +35,6 @@ 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, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import ExampleComponent from '@/components/ExampleComponent';
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen py-8">
|
<div className="min-h-screen py-8">
|
||||||
@ -19,10 +17,6 @@ export default function Home() {
|
|||||||
<li>Начните разработку!</li>
|
<li>Начните разработку!</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8">
|
|
||||||
<ExampleComponent />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,70 +0,0 @@
|
|||||||
// Пример 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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -6,9 +6,7 @@
|
|||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint"
|
||||||
"format": "prettier --write .",
|
|
||||||
"format:check": "prettier --check ."
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
@ -24,8 +22,7 @@
|
|||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.3.3",
|
"eslint-config-next": "15.3.3",
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3"
|
||||||
"prettier": "^3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user