import express from "express";
import cors from "cors";
import { fileURLToPath } from "url";
import { dirname, join, resolve } from "path";
import { healthHandler } from "./routes/health.js";
import {
listReposHandler,
listRefsHandler,
listVersionsHandler,
} from "./routes/repos.js";
import {
extractRepoHandler,
extractAllHandler,
extractionStatusHandler,
} from "./routes/extraction.js";
import {
queryNipsHandler,
queryFlowsHandler,
queryTypesHandler,
querySharedTypesHandler,
queryDataFlowHandler,
} from "./routes/queries.js";
import {
generateDiagramHandler,
generateC4DiagramHandler,
generateNipFlowDiagramHandler,
} from "./routes/diagrams.js";
import {
prImpactHandler,
diffVersionsHandler,
staleDepsHandler,
} from "./routes/comparison.js";
import { loadConfig } from "../../src/lib/config-loader.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Resolve config path relative to project root (two levels up from server/src/index.ts)
const PROJECT_ROOT = resolve(__dirname, "../..");
const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : 3001;
const FRONTEND_URL = process.env.FRONTEND_URL || "http://localhost:5173";
async function main() {
// Load config before starting server
// Config path is relative to project root
const configPath = process.env.MCP_CONFIG
? (process.env.MCP_CONFIG.startsWith("/")
? process.env.MCP_CONFIG
: resolve(PROJECT_ROOT, process.env.MCP_CONFIG))
: resolve(PROJECT_ROOT, "config/repos.yaml");
await loadConfig(configPath);
const app = express();
// Middleware
app.use(cors({ origin: FRONTEND_URL }));
app.use(express.json());
// Health check
app.get("/api/health", healthHandler);
// Repos routes
app.get("/api/repos", listReposHandler);
app.get("/api/repos/:repo/refs", listRefsHandler);
app.get("/api/repos/:repo/versions", listVersionsHandler);
// Extraction routes
app.post("/api/extract", extractRepoHandler);
app.post("/api/extract/all", extractAllHandler);
app.get("/api/extract/status/:jobId", extractionStatusHandler);
// Query routes
app.get("/api/query/nips", queryNipsHandler);
app.get("/api/query/flows", queryFlowsHandler);
app.get("/api/query/types", queryTypesHandler);
app.get("/api/query/shared-types", querySharedTypesHandler);
app.get("/api/query/data-flow", queryDataFlowHandler);
// Diagram routes
app.get("/api/diagrams", generateDiagramHandler);
app.get("/api/diagrams/c4", generateC4DiagramHandler);
app.get("/api/diagrams/nip-flow", generateNipFlowDiagramHandler);
// Comparison routes
app.post("/api/pr-impact", prImpactHandler);
app.post("/api/diff", diffVersionsHandler);
app.get("/api/stale-deps", staleDepsHandler);
// Error handling middleware
app.use(
(
err: Error,
_req: express.Request,
res: express.Response,
_next: express.NextFunction
) => {
console.error("Error:", err);
res.status(500).json({
error: "Internal server error",
message: err.message,
});
}
);
app.listen(PORT, () => {
console.log(`API server running on http://localhost:${PORT}`);
console.log(`CORS enabled for ${FRONTEND_URL}`);
});
}
main().catch((error) => {
console.error("Failed to start server:", error);
process.exit(1);
});