import "dotenv/config"; import express from "express"; import cors from "cors"; import path from "path"; import { fileURLToPath } from "url"; import { ensureTenant } from "./src/db/repo.js"; import { addSseClient, removeSseClient } from "./src/services/sse.js"; import { makeGetConversations } from "./src/controllers/conversations.js"; import { makeListRuns, makeGetRunById } from "./src/controllers/runs.js"; import { makeSimSend } from "./src/controllers/sim.js"; import { makeEvolutionWebhook } from "./src/controllers/evolution.js"; import { makeGetConversationState } from "./src/controllers/conversationState.js"; const app = express(); app.use(cors()); app.use(express.json({ limit: "1mb" })); // Serve /public as static (UI + webcomponents) const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const publicDir = path.join(__dirname, "public"); app.use(express.static(publicDir)); /** * --- Tenant --- */ const TENANT_KEY = process.env.TENANT_KEY || "piaf"; let TENANT_ID = null; function nowIso() { return new Date().toISOString(); } /** * --- SSE endpoint --- */ app.get("/stream", (req, res) => { res.setHeader("Content-Type", "text/event-stream"); res.setHeader("Cache-Control", "no-cache"); res.setHeader("Connection", "keep-alive"); res.flushHeaders?.(); res.write(`event: hello\ndata: ${JSON.stringify({ ts: nowIso() })}\n\n`); addSseClient(res); req.on("close", () => { removeSseClient(res); res.end(); }); }); /** * --- UI data endpoints --- */ app.post("/sim/send", makeSimSend()); app.get("/conversations", makeGetConversations(() => TENANT_ID)); app.get("/conversations/state", makeGetConversationState(() => TENANT_ID)); app.get("/runs", makeListRuns(() => TENANT_ID)); app.get("/runs/:run_id", makeGetRunById(() => TENANT_ID)); app.post("/webhook/evolution", makeEvolutionWebhook()); app.get("/", (req, res) => { res.sendFile(path.join(publicDir, "index.html")); }); /** * --- Boot --- */ const port = process.env.PORT || 3000; (async function boot() { TENANT_ID = await ensureTenant({ key: TENANT_KEY, name: TENANT_KEY.toUpperCase() }); app.listen(port, () => console.log(`UI: http://localhost:${port} (tenant=${TENANT_KEY})`)); })().catch((err) => { console.error("Boot failed:", err); process.exit(1); });