server/index.js Repository wynajem_motorowek Original path server/index.jsRole SOURCE Size 3553 bytes Lines 111 SHA-256 88b7e4475d59bb27987881f28873956f782d8ec5556deeeb197e5143aca138c3Displayed range 1–111 Previous file/page · Project index · Next file/page
const express = require("express");
const cors = require("cors");
const dotenv = require("dotenv");
const path = require("path");
dotenv.config();
const db = require("./db");
const resourcesRoute = require("./routes/resources");
const availabilityRoute = require("./routes/availability");
const holdsRoute = require("./routes/holds");
const paymentsRoute = require("./routes/payments");
const ownerRoute = require("./routes/owner");
const cancellationsRoute = require("./routes/cancellations");
const app = express();
const port = Number(process.env.PORT || 3030);
const webRoot = path.resolve(__dirname, "..");
const corsOrigin = String(process.env.CORS_ORIGIN || "").trim();
if (corsOrigin) {
app.use(cors({ origin: corsOrigin }));
}
app.use(express.json({ limit: "200kb" }));
app.get("/", (_req, res) => {
res.sendFile(path.join(webRoot, "index.html"));
});
app.get("/owner_menager", (_req, res) => {
res.sendFile(path.join(webRoot, "owner_manager.html"));
});
app.get("/cancel_reservation", (_req, res) => {
res.sendFile(path.join(webRoot, "cancel_reservation.html"));
});
app.get("/rezerwacja_dziekujemy.html", (_req, res) => {
res.sendFile(path.join(webRoot, "rezerwacja_dziekujemy.html"));
});
app.get("/tlo1.jpg", (_req, res) => {
res.sendFile(path.join(webRoot, "tlo1.jpg"));
});
app.use("/assets", express.static(path.join(webRoot, "assets")));
app.use("/krypy", express.static(path.join(webRoot, "krypy")));
app.get("/api/health", (_req, res) => {
res.json({ ok: true, mode: "sqlite" });
});
app.use("/api/resources", resourcesRoute({ db }));
app.use("/api/availability", availabilityRoute({ db }));
app.use("/api/holds", holdsRoute({ db }));
app.use("/api/payments", paymentsRoute({ db }));
app.use("/api/owner", ownerRoute({ db }));
app.use("/api/cancellations", cancellationsRoute({ db }));
app.use((err, _req, res, _next) => {
const hasMessage = Boolean(err && typeof err.message === "string" && err.message.trim());
const isDbAuthError = err?.code === "SQLITE_AUTH";
const isDbConnectionError = err?.code === "SQLITE_CANTOPEN";
const isNodeConnError = ["ECONNREFUSED", "ENOTFOUND", "ETIMEDOUT", "ECONNRESET"].includes(err?.code);
const isMissingDatabase = false;
const isMissingTable = err?.code === "SQLITE_ERROR" && /no such table/i.test(String(err?.message || ""));
const status = Number(
err.status || (isDbAuthError || isDbConnectionError || isNodeConnError || isMissingDatabase || isMissingTable ? 503 : 500)
);
const reason =
err.reason ||
(isDbAuthError || isDbConnectionError || isNodeConnError || isMissingDatabase || isMissingTable
? "DB_NOT_READY"
: "SERVER_ERROR");
const message = hasMessage
? err.message
: "Database not ready. Check SQLITE_PATH and server/migrations.sql";
console.error("[booking-api:error]", {
code: err?.code,
reason,
message,
});
res.status(status).json({
ok: false,
reason,
message,
});
});
setInterval(async () => {
try {
await db.query(
`UPDATE reservations
SET status = 'EXPIRED', payment_status = COALESCE(payment_status, 'EXPIRED')
WHERE status = 'HOLD' AND expires_at < ?`,
[new Date().toISOString()]
);
} catch (_err) {}
}, 60 * 1000);
db.init()
.then(() => {
app.listen(port, () => {
console.log(`[booking-api] listening on http://localhost:${port} (sqlite)`);
});
})
.catch((err) => {
console.error("[booking-api] failed to initialize sqlite database", err);
process.exit(1);
});