74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
// 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();
|
|
}
|