Files
oscars-pool/routes/version.js
T
Cursor Agentandmathieumoran1 f5bd8709a0 feat: Manage app version from admin panel
Removes GitHub dependency for app version display.

Co-authored-by: mathieumoran1 <[email protected]>
2025-12-21 22:15:15 +00:00

115 lines
3.5 KiB
JavaScript

const express = require("express");
const moment = require("moment-timezone");
const Setting = require("../models/Setting");
const router = express.Router();
const TIMEZONE = "America/New_York";
// Stored in Mongo via Setting model (admin-controlled).
// Shape:
// {
// activeId: string|null,
// versions: [{ id, version, message, dateISO }]
// }
const APP_VERSION_KEY = "app_version_control";
function nowFormatted() {
return moment(Date.now()).tz(TIMEZONE).format("YYYY-MM-DD HH:mm:ss");
}
function getPackageVersion() {
try {
// routes/version.js -> ../package.json
const pkg = require("../package.json");
return typeof pkg?.version === "string" && pkg.version.trim() ? pkg.version.trim() : "dev";
} catch (_) {
return "dev";
}
}
function normalizeAppVersionControl(rawValue) {
const v = rawValue && typeof rawValue === "object" && !Array.isArray(rawValue) ? rawValue : {};
const versions = Array.isArray(v.versions) ? v.versions : [];
const cleaned = versions
.map((e) => (e && typeof e === "object" && !Array.isArray(e) ? e : {}))
.map((e) => {
const id = typeof e.id === "string" ? e.id.trim() : "";
const version = typeof e.version === "string" ? e.version.trim() : "";
const message = typeof e.message === "string" ? e.message.slice(0, 500) : "";
const dateISO = typeof e.dateISO === "string" ? e.dateISO.trim() : "";
const d = new Date(dateISO);
const safeDateISO = dateISO && !Number.isNaN(d.getTime()) ? d.toISOString() : null;
return {
id: id || null,
version: version || null,
message: String(message || ""),
dateISO: safeDateISO,
};
})
.filter((e) => e.id && e.version)
.sort((a, b) => {
const ad = a.dateISO ? new Date(a.dateISO).getTime() : 0;
const bd = b.dateISO ? new Date(b.dateISO).getTime() : 0;
return bd - ad;
});
const activeId = typeof v.activeId === "string" ? v.activeId.trim() : "";
const active = cleaned.find((e) => String(e.id) === String(activeId)) || null;
// If activeId is invalid, fall back to newest entry.
return {
activeId: active ? String(active.id) : cleaned[0]?.id ? String(cleaned[0].id) : null,
versions: cleaned,
};
}
// Route to get the latest commit (cached)
router.get("/", async (req, res) => {
// Always return 200 and never rely on GitHub.
try {
const setting = await Setting.findOne({ key: APP_VERSION_KEY }).select("value").lean();
const control = normalizeAppVersionControl(setting?.value);
const active = control.activeId
? control.versions.find((v) => String(v.id) === String(control.activeId)) || null
: null;
if (!active) {
return res.status(200).json({
version: getPackageVersion(),
message: "Version non configurée (définis-la dans Admin → Version).",
author: "",
date: nowFormatted(),
configured: false,
source: "fallback",
});
}
const date = active.dateISO
? moment(active.dateISO).tz(TIMEZONE).format("YYYY-MM-DD HH:mm:ss")
: nowFormatted();
return res.status(200).json({
version: active.version,
message: active.message || "",
author: "",
date,
configured: true,
source: "admin",
});
} catch (_) {
// If DB is down, still return something useful.
return res.status(200).json({
version: getPackageVersion(),
message: "Version indisponible (DB).",
author: "",
date: nowFormatted(),
configured: false,
source: "fallback",
});
}
});
module.exports = router;