panel-version.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. // Mirror of web/service/panel.go isNewerVersion: parse a vMAJOR.MINOR.PATCH tag
  2. // and report whether `latest` is ahead of `current`. When either side isn't a
  3. // clean three-part numeric tag, fall back to a normalized string inequality —
  4. // the same heuristic the Go side uses so the node "update available" badge
  5. // agrees with what the server would decide.
  6. function parseVersionParts(version: string): [number, number, number] | null {
  7. const parts = version.trim().replace(/^v/, '').split('.');
  8. if (parts.length !== 3) return null;
  9. const out: number[] = [];
  10. for (const part of parts) {
  11. if (!/^\d+$/.test(part)) return null;
  12. out.push(Number(part));
  13. }
  14. return [out[0], out[1], out[2]];
  15. }
  16. // Format a panel version for display. Dev builds report a "dev+<commit>"
  17. // identity (see config.GetPanelVersion); show those — and any other
  18. // non-numeric label — verbatim. Semantic versions get a single normalized "v"
  19. // prefix, so a raw "v3.4.0" tag and a bare "3.4.0" both render as "v3.4.0"
  20. // instead of doubling up to "vv3.4.0".
  21. export function formatPanelVersion(version: string | undefined | null): string {
  22. const v = (version || '').trim();
  23. if (!v) return '';
  24. const normalized = v.replace(/^v/i, '');
  25. return /^\d/.test(normalized) ? `v${normalized}` : v;
  26. }
  27. export function isPanelUpdateAvailable(latest: string, current: string): boolean {
  28. if (!latest || !current) return false;
  29. const a = parseVersionParts(latest);
  30. const b = parseVersionParts(current);
  31. if (!a || !b) {
  32. return latest.trim().replace(/^v/, '') !== current.trim().replace(/^v/, '');
  33. }
  34. for (let i = 0; i < 3; i++) {
  35. if (a[i] > b[i]) return true;
  36. if (a[i] < b[i]) return false;
  37. }
  38. return false;
  39. }