import "dotenv/config"; import express from "express"; import { createServer } from "http"; import net from "net"; import { createExpressMiddleware } from "@trpc/server/adapters/express"; import { registerOAuthRoutes } from "./oauth"; import { appRouter } from "../routers"; import { createContext } from "./context"; import { serveStatic, setupVite } from "./vite"; import { storagePut } from "../storage"; import { nanoid } from "nanoid"; import { sdk } from "./sdk"; function isPortAvailable(port: number): Promise { 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 { 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); app.use(express.json({ limit: "60mb" })); app.use(express.urlencoded({ limit: "60mb", extended: true })); // OAuth callback under /api/oauth/callback registerOAuthRoutes(app); // Route d'upload audio (base64 → S3) app.post("/api/upload-audio", async (req, res) => { try { let user; try { user = await sdk.authenticateRequest(req); } catch { user = null; } if (!user) { res.status(401).json({ error: "Non authentifié" }); return; } const { data, contentType, filename } = req.body as { data: string; contentType: string; filename: string; }; if (!data || !contentType) { res.status(400).json({ error: "Données manquantes" }); return; } const ext = filename?.split(".").pop() ?? "mp3"; const key = `podcasts/audio/${nanoid()}.${ext}`; const buffer = Buffer.from(data, "base64"); const { url } = await storagePut(key, buffer, contentType); res.json({ key, url }); } catch (err: any) { console.error("[upload-audio]", err); res.status(500).json({ error: err.message ?? "Erreur serveur" }); } }); // tRPC API app.use( "/api/trpc", createExpressMiddleware({ router: appRouter, createContext, }) ); 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}/`); }); } startServer().catch(console.error);