84 lines
2.0 KiB
TypeScript
84 lines
2.0 KiB
TypeScript
import Fastify from "fastify";
|
|
import cors from "@fastify/cors";
|
|
import swagger from "@fastify/swagger";
|
|
import swaggerUI from "@fastify/swagger-ui";
|
|
import sensible from "@fastify/sensible";
|
|
import { env } from "./env.js";
|
|
import { ensureDatabaseReady } from "./db-init.js";
|
|
import { registerRoutes } from "./routes.js";
|
|
|
|
const app = Fastify({
|
|
disableRequestLogging: true,
|
|
logger: {
|
|
transport: {
|
|
target: "pino-pretty",
|
|
options: { colorize: true, translateTime: "SYS:standard" },
|
|
},
|
|
},
|
|
});
|
|
|
|
await ensureDatabaseReady(app.log);
|
|
|
|
await app.register(cors, {
|
|
origin: true,
|
|
credentials: true,
|
|
methods: ["GET", "HEAD", "POST", "DELETE", "OPTIONS"],
|
|
});
|
|
|
|
await app.register(swagger, {
|
|
openapi: {
|
|
info: {
|
|
title: "LLM Multiplexer Backend",
|
|
version: "0.1.0",
|
|
},
|
|
},
|
|
});
|
|
|
|
await app.register(swaggerUI, { routePrefix: "/docs" });
|
|
await app.register(sensible);
|
|
|
|
app.addHook("onRequest", async (req) => {
|
|
if (req.url.startsWith("/health")) return;
|
|
req.log.info({ method: req.method, url: req.url }, "request received");
|
|
});
|
|
|
|
app.addHook("onResponse", async (req, reply) => {
|
|
if (req.url.startsWith("/health")) return;
|
|
const responseTimeMs = typeof reply.elapsedTime === "number" ? Number(reply.elapsedTime.toFixed(1)) : undefined;
|
|
req.log.info(
|
|
{
|
|
method: req.method,
|
|
url: req.url,
|
|
statusCode: reply.statusCode,
|
|
responseTimeMs,
|
|
},
|
|
"request completed"
|
|
);
|
|
});
|
|
|
|
app.setErrorHandler((err, req, reply) => {
|
|
const e = err as any;
|
|
const statusCode = e.statusCode ?? 500;
|
|
if (!req.url.startsWith("/health")) {
|
|
req.log.error(
|
|
{
|
|
method: req.method,
|
|
url: req.url,
|
|
statusCode,
|
|
err: e,
|
|
},
|
|
"request failed"
|
|
);
|
|
}
|
|
reply.status(statusCode).send({
|
|
error: true,
|
|
message: e.message ?? String(e),
|
|
statusCode,
|
|
});
|
|
});
|
|
|
|
await registerRoutes(app);
|
|
|
|
await app.listen({ port: env.PORT, host: env.HOST });
|
|
app.log.info(`listening on http://${env.HOST}:${env.PORT}`);
|