feat: initial JaniChat messenger — PWA, WebSocket, admin panel

This commit is contained in:
Ai
2026-05-22 11:06:43 +03:00
commit 1cabe9d04f
46 changed files with 3570 additions and 0 deletions

71
backend/src/index.ts Normal file
View File

@@ -0,0 +1,71 @@
import Fastify from 'fastify';
import fastifyJwt from '@fastify/jwt';
import fastifyCors from '@fastify/cors';
import fastifyWebSocket from '@fastify/websocket';
import fastifyMultipart from '@fastify/multipart';
import fastifyStatic from '@fastify/static';
import webpush from 'web-push';
import path from 'path';
import { initDB } from './db.js';
import { setupWebSocket } from './ws.js';
import authRoutes from './routes/auth.js';
import adminRoutes from './routes/admin.js';
import chatRoutes from './routes/chats.js';
import messageRoutes from './routes/messages.js';
import userRoutes from './routes/users.js';
import pushRoutes from './routes/push.js';
const app = Fastify({ logger: true });
// VAPID
webpush.setVapidDetails(
`mailto:${process.env.VAPID_EMAIL || 'admin@janichat.ru'}`,
process.env.VAPID_PUBLIC_KEY!,
process.env.VAPID_PRIVATE_KEY!
);
// Plugins
await app.register(fastifyCors, {
origin: (process.env.ALLOWED_ORIGINS || '').split(','),
credentials: true,
});
await app.register(fastifyJwt, { secret: process.env.JWT_SECRET! });
await app.register(fastifyWebSocket);
await app.register(fastifyMultipart, {
limits: { fileSize: 50 * 1024 * 1024 },
});
await app.register(fastifyStatic, {
root: '/uploads',
prefix: '/uploads/',
});
// Auth decorator
app.decorate('authenticate', async function(request: any, reply: any) {
try {
await request.jwtVerify();
} catch {
reply.status(401).send({ error: 'Unauthorized' });
}
});
// Routes
await app.register(authRoutes, { prefix: '/api/auth' });
await app.register(adminRoutes, { prefix: '/api/admin' });
await app.register(chatRoutes, { prefix: '/api/chats' });
await app.register(messageRoutes, { prefix: '/api/messages' });
await app.register(userRoutes, { prefix: '/api/users' });
await app.register(pushRoutes, { prefix: '/api/push' });
// Health check
app.get('/health', async () => ({ ok: true }));
// WebSocket
setupWebSocket(app);
// Init
await initDB();
await app.listen({ port: parseInt(process.env.PORT || '3000'), host: '0.0.0.0' });