@x-tech-laboratories/x-libs 0.2.0 → 0.3.0
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/README.md +12 -5
- package/dist/agent/client.d.ts +9 -6
- package/dist/agent/client.js +3 -3
- package/dist/agent/keys.js +31 -119
- package/dist/agent/long_runs.d.ts +5 -5
- package/dist/agent/long_runs.js +9 -10
- package/dist/agent/protocol.d.ts +20 -14
- package/dist/agent/protocol.js +34 -17
- package/dist/agent/session.d.ts +11 -8
- package/dist/agent/session.js +13 -9
- package/dist/agent/tasks.d.ts +17 -0
- package/dist/agent/tasks.js +15 -0
- package/dist/durations.js +18 -20
- package/dist/server/agents/agent.d.ts +4 -4
- package/dist/server/agents/connection.d.ts +8 -7
- package/dist/server/agents/connection.js +11 -9
- package/dist/server/agents/hub.d.ts +12 -12
- package/dist/server/agents/hub.js +14 -14
- package/dist/server/agents/local.d.ts +10 -7
- package/dist/server/agents/local.js +12 -9
- package/dist/server/agents/route.d.ts +1 -1
- package/dist/server/hash_password.js +16 -34
- package/dist/web/format.js +25 -29
- package/package.json +9 -2
package/dist/web/format.js
CHANGED
|
@@ -1,26 +1,36 @@
|
|
|
1
1
|
// Writes times, durations, sizes and counts short enough for a table cell.
|
|
2
|
+
import pretty_bytes from "pretty-bytes";
|
|
2
3
|
// ── Times ────────────────────────────────────────────────────────────────────
|
|
3
4
|
export function now_seconds() {
|
|
4
5
|
return Date.now() / 1000;
|
|
5
6
|
}
|
|
7
|
+
const relative = new Intl.RelativeTimeFormat("en", { style: "narrow", numeric: "always" });
|
|
8
|
+
const plurals = new Intl.PluralRules("en");
|
|
9
|
+
// A whole number of the largest unit that reads well, such as -3 hours, for "3h ago" or "in 3h".
|
|
10
|
+
function relative_time(seconds) {
|
|
11
|
+
const magnitude = Math.abs(seconds);
|
|
12
|
+
const sign = seconds < 0 ? -1 : 1;
|
|
13
|
+
if (magnitude < 90)
|
|
14
|
+
return relative.format(sign * Math.round(magnitude), "second");
|
|
15
|
+
if (magnitude < 5400)
|
|
16
|
+
return relative.format(sign * Math.round(magnitude / 60), "minute");
|
|
17
|
+
if (magnitude < 129600)
|
|
18
|
+
return relative.format(sign * Math.round(magnitude / 3600), "hour");
|
|
19
|
+
return relative.format(sign * Math.round(magnitude / 86400), "day");
|
|
20
|
+
}
|
|
6
21
|
export function age(epoch) {
|
|
7
22
|
if (!epoch)
|
|
8
23
|
return "never";
|
|
9
|
-
|
|
10
|
-
if (seconds < 90)
|
|
11
|
-
return `${Math.round(seconds)}s ago`;
|
|
12
|
-
if (seconds < 5400)
|
|
13
|
-
return `${Math.round(seconds / 60)}m ago`;
|
|
14
|
-
if (seconds < 129600)
|
|
15
|
-
return `${Math.round(seconds / 3600)}h ago`;
|
|
16
|
-
return `${Math.round(seconds / 86400)}d ago`;
|
|
24
|
+
return relative_time(-Math.max(0, now_seconds() - epoch));
|
|
17
25
|
}
|
|
18
|
-
// How long until the epoch, such as "in 3d", or how long ago
|
|
26
|
+
// How long until the epoch, such as "in 3d", "now" when it is less than 90 seconds off, or how long ago once passed.
|
|
19
27
|
export function until(epoch) {
|
|
20
28
|
if (epoch === null)
|
|
21
29
|
return "—";
|
|
22
30
|
const seconds = epoch - now_seconds();
|
|
23
|
-
|
|
31
|
+
if (seconds < 0)
|
|
32
|
+
return age(epoch);
|
|
33
|
+
return seconds < 90 ? "now" : relative_time(seconds);
|
|
24
34
|
}
|
|
25
35
|
export function duration(seconds) {
|
|
26
36
|
if (seconds === null)
|
|
@@ -42,33 +52,19 @@ export function stamp(epoch) {
|
|
|
42
52
|
// ── Sizes ────────────────────────────────────────────────────────────────────
|
|
43
53
|
// Sizes in binary units, such as "44.4 GiB".
|
|
44
54
|
export function bytes(count) {
|
|
45
|
-
|
|
46
|
-
let value = count;
|
|
47
|
-
let unit = 0;
|
|
48
|
-
while (value >= 1024 && unit < units.length - 1) {
|
|
49
|
-
value /= 1024;
|
|
50
|
-
unit += 1;
|
|
51
|
-
}
|
|
52
|
-
return unit === 0 ? `${Math.round(value)} B` : `${value.toFixed(1)} ${units[unit]}`;
|
|
55
|
+
return pretty_bytes(count, { binary: true, maximumFractionDigits: 1 });
|
|
53
56
|
}
|
|
54
57
|
// Sizes in decimal units, such as "1.2 GB".
|
|
55
58
|
export function size(count) {
|
|
56
59
|
if (count === null || count === undefined)
|
|
57
60
|
return "—";
|
|
58
|
-
|
|
59
|
-
let value = Math.abs(count);
|
|
60
|
-
let unit = 0;
|
|
61
|
-
while (value >= 1000 && unit < units.length - 1) {
|
|
62
|
-
value /= 1000;
|
|
63
|
-
unit += 1;
|
|
64
|
-
}
|
|
65
|
-
return `${count < 0 ? "−" : ""}${value.toFixed(value < 10 && unit > 0 ? 1 : 0)} ${units[unit]}`;
|
|
61
|
+
return pretty_bytes(count, { maximumFractionDigits: 1 });
|
|
66
62
|
}
|
|
67
|
-
// A size change with its sign, such as +1.2 GB or
|
|
63
|
+
// A size change with its sign, such as +1.2 GB or -300 MB.
|
|
68
64
|
export function size_change(count) {
|
|
69
65
|
if (count === null || count === undefined)
|
|
70
66
|
return "—";
|
|
71
|
-
return count
|
|
67
|
+
return count === 0 ? size(0) : pretty_bytes(count, { signed: true, maximumFractionDigits: 1 });
|
|
72
68
|
}
|
|
73
69
|
// ── Counts ───────────────────────────────────────────────────────────────────
|
|
74
70
|
export function count_change(value) {
|
|
@@ -77,5 +73,5 @@ export function count_change(value) {
|
|
|
77
73
|
return value > 0 ? `+${value.toLocaleString()}` : value < 0 ? `−${Math.abs(value).toLocaleString()}` : "0";
|
|
78
74
|
}
|
|
79
75
|
export function plural(count, word) {
|
|
80
|
-
return `${count.toLocaleString()} ${word}${count ===
|
|
76
|
+
return `${count.toLocaleString()} ${word}${plurals.select(count) === "one" ? "" : "s"}`;
|
|
81
77
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x-tech-laboratories/x-libs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Code the X-apps share: agents and their long runs, passwords, durations, and the web page's helpers and widgets",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"build": "tsc -b",
|
|
25
25
|
"test": "vitest run",
|
|
26
26
|
"lint": "oxlint",
|
|
27
|
-
"
|
|
27
|
+
"prepack": "npm run build"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"@fastify/websocket": "^11.3.5",
|
|
@@ -45,10 +45,17 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@fastify/websocket": "^11.3.5",
|
|
47
47
|
"@types/node": "^24.19.2",
|
|
48
|
+
"@types/sshpk": "^1.17.5",
|
|
48
49
|
"fastify": "^5.12.7",
|
|
49
50
|
"oxlint": "^1.90.0",
|
|
50
51
|
"preact": "^10.29.8",
|
|
51
52
|
"typescript": "^7.0.2",
|
|
52
53
|
"vitest": "^5.0.5"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@inquirer/password": "^5.2.5",
|
|
57
|
+
"parse-duration": "^2.1.11",
|
|
58
|
+
"pretty-bytes": "^7.2.0",
|
|
59
|
+
"sshpk": "^1.18.0"
|
|
53
60
|
}
|
|
54
61
|
}
|