Files
formation-manager-itinova/server/_core/index.ts

90 lines
2.9 KiB
TypeScript

import "dotenv/config";
import express from "express";
import { createServer } from "http";
import net from "net";
import path from "path";
import { createExpressMiddleware } from "@trpc/server/adapters/express";
import { registerOAuthRoutes } from "./oauth";
import { appRouter } from "../routers";
import { createContext } from "./context";
import localAuthRouter from "./localAuth";
import uploadImageRouter from "./uploadImage";
import uploadFileRouter from "./uploadFile";
import { serveStatic, setupVite } from "./vite";
import { initRappelScheduler } from "../rappelScheduler";
import { initRappelRetryScheduler } from "../rappelRetry";
import { initFail2BanAlertSystem } from "../fail2banAlertService";
function isPortAvailable(port: number): Promise<boolean> {
return new Promise(resolve => {
const server = net.createServer();
server.listen(port, () => {
server.close(() => resolve(true));
});
server.on("error", () => resolve(false));
});
}
async function findAvailablePort(startPort: number = 3000): Promise<number> {
for (let port = startPort; port < startPort + 20; port++) {
if (await isPortAvailable(port)) {
return port;
}
}
throw new Error(`No available port found starting from ${startPort}`);
}
async function startServer() {
const app = express();
const server = createServer(app);
// Configure body parser with larger size limit for file uploads
app.use(express.json({ limit: "50mb" }));
app.use(express.urlencoded({ limit: "50mb", extended: true }));
// OAuth callback under /api/oauth/callback
registerOAuthRoutes(app);
// Local authentication under /api/auth/local
app.use("/api/auth/local", localAuthRouter);
// Image upload under /api/upload-image
app.use("/api/upload-image", uploadImageRouter);
// File upload under /api/upload-file
app.use("/api/upload-file", uploadFileRouter);
// Serve uploaded files
app.use("/uploads", express.static(path.join(process.cwd(), "uploads")));
// tRPC API
app.use(
"/api/trpc",
createExpressMiddleware({
router: appRouter,
createContext,
})
);
// development mode uses Vite, production mode uses static files
if (process.env.NODE_ENV === "development") {
await setupVite(app, server);
} else {
serveStatic(app);
}
const preferredPort = parseInt(process.env.PORT || "3000");
const port = await findAvailablePort(preferredPort);
if (port !== preferredPort) {
console.log(`Port ${preferredPort} is busy, using port ${port} instead`);
}
server.listen(port, () => {
console.log(`Server running on http://localhost:${port}/`);
// Initialiser le scheduler de rappels automatiques
initRappelScheduler();
// Initialiser le scheduler de réessai automatique
initRappelRetryScheduler();
// Initialiser le système d'alertes Fail2Ban
initFail2BanAlertSystem();
});
}
startServer().catch(console.error);