Files
fasto/backend/index.js
2026-05-29 15:23:01 -03:00

117 lines
3.8 KiB
JavaScript

require('dotenv').config();
const express = require('express');
const path = require('path');
const multer = require('multer');
const { v4: uuidv4 } = require('uuid');
const fs = require('fs');
const pool = require('./db');
const transporter = require('./services/mailer');
const { provisionSuperAdmin } = require('./services/provisioning');
const { createCorsMiddleware } = require('./config/cors');
const { allowedOrigins, getBaseUrl, getStartupBaseUrl, isProduction, jwtSecret: JWT_SECRET, port: PORT } = require('./config/runtime');
const { authenticateToken } = require('./middleware/auth');
const { createAuthRouter } = require('./routes/authRoutes');
const { createUsersRouter } = require('./routes/usersRoutes');
const { createTeamsRouter } = require('./routes/teamsRoutes');
const { createTenantsRouter } = require('./routes/tenantsRoutes');
const { createActivityRouter } = require('./routes/activityRoutes');
const { createOriginsRouter } = require('./routes/originsRoutes');
const { createFunnelsRouter } = require('./routes/funnelsRoutes');
const { createSearchRouter } = require('./routes/searchRoutes');
const { createAttendancesRouter } = require('./routes/attendancesRoutes');
const { createApiKeysRouter } = require('./routes/apiKeysRoutes');
const { createIntegrationsRouter } = require('./routes/integrationsRoutes');
const app = express();
app.use(createCorsMiddleware({ allowedOrigins, isProduction }));
app.use(express.json());
// Logger de Requisições
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
// --- Configuração Multer (Upload Seguro) ---
const uploadDir = path.join(__dirname, 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, uploadDir);
},
filename: (req, file, cb) => {
const ext = path.extname(file.originalname).toLowerCase();
cb(null, `${uuidv4()}${ext}`);
}
});
const upload = multer({
storage: storage,
limits: { fileSize: 2 * 1024 * 1024 }, // 2MB
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Tipo de arquivo inválido. Apenas JPG, PNG e WEBP são permitidos.'));
}
}
});
app.use('/uploads', express.static(uploadDir, {
setHeaders: (res) => {
res.set('X-Content-Type-Options', 'nosniff');
}
}));
// --- API Router ---
const apiRouter = express.Router();
apiRouter.use(authenticateToken);
// --- Auth Routes ---
apiRouter.use(createAuthRouter({ pool, transporter, getBaseUrl, jwtSecret: JWT_SECRET }));
apiRouter.use(createUsersRouter({ pool, upload, transporter, getBaseUrl }));
apiRouter.use(createTeamsRouter({ pool }));
apiRouter.use(createTenantsRouter({ pool, transporter, getBaseUrl }));
apiRouter.use(createActivityRouter({ pool }));
apiRouter.use(createOriginsRouter({ pool }));
apiRouter.use(createFunnelsRouter({ pool }));
apiRouter.use(createSearchRouter({ pool }));
apiRouter.use(createAttendancesRouter({ pool }));
apiRouter.use(createApiKeysRouter({ pool }));
apiRouter.use(createIntegrationsRouter({ pool }));
// Mount the API Router
app.use('/api', apiRouter);
// Serve static files
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, 'dist')));
app.get('*', (req, res) => {
// Avoid hijacking API requests
if (req.url.startsWith('/api')) return res.status(404).json({ error: 'API route not found' });
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
}
app.listen(PORT, async () => {
await provisionSuperAdmin({ pool, transporter, getStartupBaseUrl });
console.log(`🚀 Servidor Backend rodando em http://localhost:${PORT}`);
});