remote-version.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import https from "node:https";
  2. import { ProxyAgent } from "proxy-agent";
  3. import { debug, remoteVersion as logger } from "../logger.js";
  4. import pjson from "../package.json" with { type: "json" };
  5. const VERSION_URL = "https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest";
  6. const internalRemoteVersion = {
  7. cache_timeout: 1000 * 60 * 15, // 15 minutes
  8. last_result: null,
  9. last_fetch_time: null,
  10. /**
  11. * Fetch the latest version info, using a cached result if within the cache timeout period.
  12. * @return {Promise<{current: string, latest: string, update_available: boolean}>} Version info
  13. */
  14. get: async () => {
  15. if (
  16. !internalRemoteVersion.last_result ||
  17. !internalRemoteVersion.last_fetch_time ||
  18. Date.now() - internalRemoteVersion.last_fetch_time > internalRemoteVersion.cache_timeout
  19. ) {
  20. const raw = await internalRemoteVersion.fetchUrl(VERSION_URL);
  21. const data = JSON.parse(raw);
  22. internalRemoteVersion.last_result = data;
  23. internalRemoteVersion.last_fetch_time = Date.now();
  24. } else {
  25. debug(logger, "Using cached remote version result");
  26. }
  27. const latestVersion = internalRemoteVersion.last_result.tag_name;
  28. const version = pjson.version.split("-").shift().split(".");
  29. const currentVersion = `v${version[0]}.${version[1]}.${version[2]}`;
  30. return {
  31. current: currentVersion,
  32. latest: latestVersion,
  33. update_available: internalRemoteVersion.compareVersions(currentVersion, latestVersion),
  34. };
  35. },
  36. fetchUrl: (url) => {
  37. const agent = new ProxyAgent();
  38. const headers = {
  39. "User-Agent": `NginxProxyManager v${pjson.version}`,
  40. };
  41. return new Promise((resolve, reject) => {
  42. logger.info(`Fetching ${url}`);
  43. return https
  44. .get(url, { agent, headers }, (res) => {
  45. res.setEncoding("utf8");
  46. let raw_data = "";
  47. res.on("data", (chunk) => {
  48. raw_data += chunk;
  49. });
  50. res.on("end", () => {
  51. resolve(raw_data);
  52. });
  53. })
  54. .on("error", (err) => {
  55. reject(err);
  56. });
  57. });
  58. },
  59. compareVersions: (current, latest) => {
  60. const cleanCurrent = current.replace(/^v/, "");
  61. const cleanLatest = latest.replace(/^v/, "");
  62. const currentParts = cleanCurrent.split(".").map(Number);
  63. const latestParts = cleanLatest.split(".").map(Number);
  64. for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
  65. const curr = currentParts[i] || 0;
  66. const lat = latestParts[i] || 0;
  67. if (lat > curr) return true;
  68. if (lat < curr) return false;
  69. }
  70. return false;
  71. },
  72. };
  73. export default internalRemoteVersion;