diff options
| author | zwlucas <lucas.fariamo08@gmail.com> | 2026-07-25 21:23:29 +0000 |
|---|---|---|
| committer | zwlucas <lucas.fariamo08@gmail.com> | 2026-07-25 21:23:29 +0000 |
| commit | ef55d9bb24430610b60c1b77821307cd72c08c55 (patch) | |
| tree | e6935a810b34370b0a4c821e55f6397aac50c832 /api/src/server.ts | |
| download | helpdesk-ef55d9bb24430610b60c1b77821307cd72c08c55.tar.gz helpdesk-ef55d9bb24430610b60c1b77821307cd72c08c55.zip | |
Signed-off-by: zwlucas <lucas.fariamo08@gmail.com>
Diffstat (limited to 'api/src/server.ts')
| -rw-r--r-- | api/src/server.ts | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/api/src/server.ts b/api/src/server.ts new file mode 100644 index 0000000..9ab75eb --- /dev/null +++ b/api/src/server.ts @@ -0,0 +1,115 @@ +/** + * server.ts + * + * Entry point do backend Helpdesk. + * + * Responsabilidades (em ordem): + * 1. Executar migrações do banco no boot + * 2. Criar e configurar a instância Fastify + * 3. Registrar plugins globais + * 4. Registrar módulos de rotas + * 5. Iniciar o servidor HTTP + */ + +import 'dotenv/config'; // Carrega .env antes de qualquer outro import +import Fastify from 'fastify'; +import cors from '@fastify/cors'; +import sensible from '@fastify/sensible'; +import { validatorCompiler } from 'fastify-type-provider-zod'; + +import { runMigrations } from '@/db/migrate.js'; +import dbPlugin from '@/plugins/db.plugin.js'; +import authPlugin from '@/plugins/auth.plugin.js'; +import authRoutes from '@/modules/auth/auth.routes.js'; +import ticketsRoutes from '@/modules/tickets/tickets.routes.js'; +import interactionsRoutes from '@/modules/interactions/interactions.routes.js'; +import categoriesRoutes from '@/modules/categories/categories.routes.js'; +import settingsRoutes from '@/modules/settings/settings.routes.js'; +import statsRoutes from '@/modules/stats/stats.routes.js'; +import usersRoutes from '@/modules/users/users.routes.js'; +import eventsPlugin from '@/plugins/events.plugin.js'; +import eventsRoutes from '@/plugins/events.routes.js'; + +// ─── Configuração ───────────────────────────────────────────────────────────── +const PORT = Number(process.env['PORT'] ?? 3000); +const HOST = process.env['HOST'] ?? '0.0.0.0'; +const IS_DEV = process.env['NODE_ENV'] !== 'production'; + +// ─── Factory da aplicação ───────────────────────────────────────────────────── +// Exportar como função facilita testes de integração (cada teste cria uma instância) +export async function buildApp() { + const fastify = Fastify({ + logger: { + level: IS_DEV ? 'info' : 'warn', + // Formatação legível no terminal em desenvolvimento + transport: IS_DEV + ? { target: 'pino-pretty', options: { colorize: true } } + : undefined, + }, + }); + + // Configura o Fastify para usar validação com Zod + fastify.setValidatorCompiler(validatorCompiler); + + // ── Plugins Globais ─────────────────────────────────────────────────────── + // CORS: permite requisições do frontend (Vite roda na porta 5173) + await fastify.register(cors, { + origin: IS_DEV ? 'http://localhost:5173' : process.env['FRONTEND_URL'], + methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], + }); + + // Sensible: adiciona helpers como reply.notFound(), reply.badRequest(), etc. + await fastify.register(sensible); + + // Banco de dados: disponibiliza fastify.db em todas as rotas + await fastify.register(dbPlugin); + + // JWT: disponibiliza fastify.authenticate em todas as rotas + await fastify.register(authPlugin); + + // ── Plugins Locais ──────────────────────────────────────────────────────── + await fastify.register(eventsPlugin); + + // ── Rotas ───────────────────────────────────────────────────────────────── + // Auth: rotas públicas (sem authenticate) + await fastify.register(authRoutes, { prefix: '/api/v1/auth' }); + await fastify.register(statsRoutes, { prefix: '/api/v1/stats' }); + await fastify.register(eventsRoutes, { prefix: '/api/v1/events' }); + await fastify.register(categoriesRoutes, { prefix: '/api/v1/categories' }); + await fastify.register(settingsRoutes, { prefix: '/api/v1/settings' }); + await fastify.register(usersRoutes, { prefix: '/api/v1/users' }); + await fastify.register(ticketsRoutes, { prefix: '/api/v1/tickets' }); + await fastify.register(interactionsRoutes, { prefix: '/api/v1' }); + + // Health check — útil para monitoramento e load balancer + fastify.get('/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() })); + + return fastify; +} + +// ─── Bootstrap ─────────────────────────────────────────────────────────────── +async function start(): Promise<void> { + // 1. Aplica migrações pendentes antes de abrir o servidor para tráfego + await runMigrations(); + + // 2. Cria a instância configurada + const app = await buildApp(); + + // 3. Graceful shutdown — garante que requests em andamento terminem antes de fechar + const gracefulShutdown = async (signal: string) => { + app.log.info(`Sinal ${signal} recebido. Encerrando servidor...`); + await app.close(); + process.exit(0); + }; + + process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); // Kubernetes / systemd + process.on('SIGINT', () => gracefulShutdown('SIGINT')); // Ctrl+C no terminal + + // 4. Inicia o servidor + await app.listen({ port: PORT, host: HOST }); +} + +start().catch((err) => { + console.error('❌ Falha ao iniciar o servidor:', err); + process.exit(1); +}); |