@pi-unipi/updater 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/checker.ts +23 -16
- package/src/version.ts +36 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "Auto-updater, changelog browser, and readme browser for Unipi — checks npm registry, renders CHANGELOG.md and README.md files in TUI overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/checker.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { getInstalledPackageVersion } from "@pi-unipi/core";
|
|
9
9
|
import { loadConfig } from "./settings.js";
|
|
10
10
|
import { readLastCheck, writeLastCheck, isCheckDue } from "./cache.js";
|
|
11
|
+
import { compareVersions, isNewerVersion } from "./version.js";
|
|
11
12
|
import type { UpdateCheckResult } from "../types.js";
|
|
12
13
|
|
|
13
14
|
/** NPM registry URL for the unipi umbrella package */
|
|
@@ -20,6 +21,16 @@ function getInstalledVersion(): string {
|
|
|
20
21
|
return getInstalledPackageVersion(dir, "@pi-unipi/unipi");
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
|
|
25
|
+
/** Build an update result without ever reporting downgrades as updates. */
|
|
26
|
+
function toUpdateResult(latestVersion: string, currentVersion: string): UpdateCheckResult {
|
|
27
|
+
return {
|
|
28
|
+
updateAvailable: isNewerVersion(latestVersion, currentVersion),
|
|
29
|
+
latestVersion,
|
|
30
|
+
currentVersion,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
23
34
|
/**
|
|
24
35
|
* Check for updates from npm registry.
|
|
25
36
|
* Respects check interval — skips if last check was recent.
|
|
@@ -31,15 +42,14 @@ export async function checkForUpdates(): Promise<UpdateCheckResult> {
|
|
|
31
42
|
try {
|
|
32
43
|
const config = loadConfig();
|
|
33
44
|
|
|
34
|
-
// Check if we need to fetch (interval not elapsed)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
};
|
|
45
|
+
// Check if we need to fetch (interval not elapsed). If the cached npm
|
|
46
|
+
// version is older than the installed version, ignore the interval and
|
|
47
|
+
// refresh: this happens immediately after a local/source release before
|
|
48
|
+
// the updater cache has seen the new npm dist-tag.
|
|
49
|
+
const cache = readLastCheck();
|
|
50
|
+
if (cache && !isCheckDue(config.checkIntervalMs)) {
|
|
51
|
+
if (compareVersions(cache.latestVersion, currentVersion) >= 0) {
|
|
52
|
+
return toUpdateResult(cache.latestVersion, currentVersion);
|
|
43
53
|
}
|
|
44
54
|
}
|
|
45
55
|
|
|
@@ -66,16 +76,13 @@ export async function checkForUpdates(): Promise<UpdateCheckResult> {
|
|
|
66
76
|
latestVersion,
|
|
67
77
|
});
|
|
68
78
|
|
|
69
|
-
return
|
|
70
|
-
updateAvailable: latestVersion !== currentVersion,
|
|
71
|
-
latestVersion,
|
|
72
|
-
currentVersion,
|
|
73
|
-
};
|
|
79
|
+
return toUpdateResult(latestVersion, currentVersion);
|
|
74
80
|
} catch (err: unknown) {
|
|
75
|
-
// Network error — return cached info if available
|
|
81
|
+
// Network error — return cached info if available, but never suggest a
|
|
82
|
+
// downgrade from a stale cache.
|
|
76
83
|
const cache = readLastCheck();
|
|
77
84
|
return {
|
|
78
|
-
updateAvailable: false,
|
|
85
|
+
updateAvailable: cache ? isNewerVersion(cache.latestVersion, currentVersion) : false,
|
|
79
86
|
latestVersion: cache?.latestVersion ?? "",
|
|
80
87
|
currentVersion,
|
|
81
88
|
error: err instanceof Error ? err.message : String(err) || "Unknown error",
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pi-unipi/updater — version comparison helpers
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Compare two semver-ish version strings.
|
|
7
|
+
* Returns 1 when a > b, -1 when a < b, 0 when equal.
|
|
8
|
+
*
|
|
9
|
+
* This intentionally handles the simple versions Unipi publishes (x.y.z)
|
|
10
|
+
* without adding a runtime dependency. Non-numeric suffixes are ignored for
|
|
11
|
+
* ordering, so `2.0.5` and `v2.0.5` compare equal.
|
|
12
|
+
*/
|
|
13
|
+
export function compareVersions(a: string, b: string): number {
|
|
14
|
+
const parse = (version: string): number[] => version
|
|
15
|
+
.replace(/^v/, "")
|
|
16
|
+
.split(/[.-]/)
|
|
17
|
+
.slice(0, 3)
|
|
18
|
+
.map((part) => {
|
|
19
|
+
const parsed = Number.parseInt(part, 10);
|
|
20
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const left = parse(a);
|
|
24
|
+
const right = parse(b);
|
|
25
|
+
for (let i = 0; i < 3; i++) {
|
|
26
|
+
const diff = (left[i] ?? 0) - (right[i] ?? 0);
|
|
27
|
+
if (diff > 0) return 1;
|
|
28
|
+
if (diff < 0) return -1;
|
|
29
|
+
}
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Return true only when `latest` is newer than `current`. */
|
|
34
|
+
export function isNewerVersion(latest: string, current: string): boolean {
|
|
35
|
+
return compareVersions(latest, current) > 0;
|
|
36
|
+
}
|