// ShopApp — Fastify Backend Server import Fastify from "fastify"; import cors from "@fastify/cors"; import fjwt from "@fastify/jwt"; import { initDb, closeDb } from "./db/client.js"; import { authRoutes } from "./routes/auth.js"; import { productsRoutes } from "./routes/products.js"; import { ordersRoutes } from "./routes/orders.js"; import { stocktakingRoutes } from "./routes/stocktaking.js"; import { suppliersRoutes } from "./routes/suppliers.js"; import { stock_alertsRoutes } from "./routes/stock_alerts.js"; const JWT_SECRET = process.env.JWT_SECRET || "change-me-in-production-3562fed5"; export async function buildApp() { const app = Fastify({ logger: { level: process.env.LOG_LEVEL || "info", transport: process.env.NODE_ENV !== "production" ? { target: "pino-pretty", options: { colorize: true } } : undefined, }, }); // Init database await initDb(); // Plugins await app.register(cors, { origin: process.env.CORS_ORIGIN || "*", methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"], }); await app.register(fjwt, { secret: JWT_SECRET }); // Routes await app.register(authRoutes, { prefix: "/api/auth" }); await app.register(productsRoutes, { prefix: "/api/products" }); await app.register(ordersRoutes, { prefix: "/api/orders" }); await app.register(stocktakingRoutes, { prefix: "/api/stocktaking" }); await app.register(suppliersRoutes, { prefix: "/api/suppliers" }); await app.register(stock_alertsRoutes, { prefix: "/api/stock_alerts" }); // Health check app.get("/api/health", async () => ({ status: "ok", timestamp: new Date().toISOString() })); // Graceful shutdown app.addHook("onClose", async () => { closeDb(); }); return app; } // Start server if called directly (not when imported by tests) const port = parseInt(process.env.PORT || "3001", 10); const host = process.env.HOST || "0.0.0.0"; async function main() { const app = await buildApp(); try { await app.listen({ port, host }); } catch (err) { app.log.error(err); process.exit(1); } } // Guard: only run when executed directly, not when imported const isMain = process.argv[1] && (import.meta.url === `file://${process.argv[1]}` || import.meta.url.endsWith(process.argv[1]) || process.argv[1].endsWith("/src/index.ts") || process.argv[1].endsWith("/src/index.js")); if (isMain) { main(); }