feat(card1): версии тестов API, черновик, HR-login, import, UI

- V.1–V.3: saveTestDraft, fork при попытках; миграция 003 staff_id
- V.4–V.6: REST /api/tests, activate, PATCH, start attempt
- A: HR_DATABASE_URL + Werkzeug/bcrypt, JWT staffId, HR_AUTH
- D.1: multipart /api/tests/import/document
- Frontend: login, список тестов, экран версий/черновика/попытки
- ТЗ: V.10 назначения vs активная версия; журнал приёма

Made-with: Cursor
This commit is contained in:
Константин Лебединский
2026-04-24 20:30:09 +05:00
parent 7fa6f98ee1
commit 5631d85238
37 changed files with 9687 additions and 59 deletions
+45
View File
@@ -0,0 +1,45 @@
import express from 'express';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import dotenv from 'dotenv';
import authRoutes from './routes/auth.js';
import testsRoutes from './routes/tests.js';
dotenv.config();
export function createApp() {
const app = express();
const corsOrigins =
process.env.NODE_ENV === 'production'
? process.env.FRONTEND_URL
? [process.env.FRONTEND_URL]
: []
: ['http://localhost:5173', 'http://localhost:3000'];
app.use(
cors({
origin: corsOrigins.length ? corsOrigins : true,
credentials: true,
})
);
app.use(express.json());
app.use(cookieParser());
app.use('/api/auth', authRoutes);
app.use('/api/tests', testsRoutes);
app.get('/api/health', (req, res) => {
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
message: 'Server is running',
});
});
app.use((err, req, res, _next) => {
console.error('Error:', err);
res.status(err.status || 500).json({
error: err.message || 'Internal Server Error',
});
});
app.use((req, res) => {
res.status(404).json({ error: 'Not found' });
});
return app;
}