version.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import express from "express";
  2. import { debug, express as logger } from "../logger.js";
  3. import pjson from "../package.json" with { type: "json" };
  4. import https from "node:https";
  5. import { ProxyAgent } from "proxy-agent";
  6. const router = express.Router({
  7. caseSensitive: true,
  8. strict: true,
  9. mergeParams: true,
  10. });
  11. /**
  12. * /api/version/check
  13. */
  14. router
  15. .route("/check")
  16. .options((_, res) => {
  17. res.sendStatus(204);
  18. })
  19. /**
  20. * GET /api/version/check
  21. *
  22. * Check for available updates
  23. */
  24. .get(async (req, res, next) => {
  25. try {
  26. const agent = new ProxyAgent();
  27. const url = "https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest";
  28. const data = await new Promise((resolve, reject) => {
  29. https
  30. .get(url, { agent }, (response) => {
  31. if (response.statusCode !== 200) {
  32. reject(new Error(`GitHub API returned ${response.statusCode}`));
  33. return;
  34. }
  35. response.setEncoding("utf8");
  36. let raw_data = "";
  37. response.on("data", (chunk) => {
  38. raw_data += chunk;
  39. });
  40. response.on("end", () => {
  41. try {
  42. resolve(JSON.parse(raw_data));
  43. } catch (err) {
  44. reject(err);
  45. }
  46. });
  47. })
  48. .on("error", (err) => {
  49. reject(err);
  50. });
  51. });
  52. const latestVersion = data.tag_name;
  53. const version = pjson.version.split("-").shift().split(".");
  54. const currentVersion = `v${version[0]}.${version[1]}.${version[2]}`;
  55. res.status(200).send({
  56. current: currentVersion,
  57. latest: latestVersion,
  58. updateAvailable: compareVersions(currentVersion, latestVersion),
  59. });
  60. } catch (error) {
  61. debug(logger, `${req.method.toUpperCase()} ${req.path}: ${error}`);
  62. res.status(200).send({
  63. current: null,
  64. latest: null,
  65. updateAvailable: false,
  66. });
  67. }
  68. });
  69. /**
  70. * Compare two version strings
  71. *
  72. */
  73. function compareVersions(current, latest) {
  74. const cleanCurrent = current.replace(/^v/, "");
  75. const cleanLatest = latest.replace(/^v/, "");
  76. const currentParts = cleanCurrent.split(".").map(Number);
  77. const latestParts = cleanLatest.split(".").map(Number);
  78. for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
  79. const curr = currentParts[i] || 0;
  80. const lat = latestParts[i] || 0;
  81. if (lat > curr) return true;
  82. if (lat < curr) return false;
  83. }
  84. return false;
  85. }
  86. export default router;