@yourfam/yf-vitals 0.3.0 → 0.3.2

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 CHANGED
@@ -36,10 +36,10 @@ One live dashboard. Refresh every **1.0s** (or `--interval`, or **2.0s** with `-
36
36
  |---|---|
37
37
  | **CPU** | Overall utilization 0–100%, plus physical / logical core counts |
38
38
  | **RAM** | Percent used, plus used / total (`GiB` / `MiB`) |
39
- | **USE** | Local hard-disk fill (system volume first). Skips Google Drive, iCloud, network, FAT/USB. Extra local disks as extra lines |
39
+ | **GPU** | Utilization and VRAM when telemetry exists; **the row is omitted** when it does not |
40
40
  | **DSK** | Read and write **rates** (KiB/s, MiB/s, GiB/s) |
41
41
  | **NET** | Send ↑ and receive ↓ in **kbps / Mbps / Gbps** (decimal bits; 1 Mbps = 1e6 bit/s) |
42
- | **GPU** | Utilization and VRAM when telemetry exists; **the row is omitted** when it does not |
42
+ | **C: / D: / Data** | Capacity last: one bar per local partition. Skips Google Drive, iCloud, network, FAT/USB |
43
43
 
44
44
  Header: `yf-vitals` · hostname · OS · `NP/NL` cores · RAM total · tick interval.
45
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yourfam/yf-vitals",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Live terminal dashboard for CPU, RAM, disk, net, and optional GPU",
5
5
  "type": "module",
6
6
  "bin": {
package/src/args.js CHANGED
@@ -98,7 +98,7 @@ Usage:
98
98
  --version, -V Package version
99
99
 
100
100
  q / Q / Ctrl+C quit. GPU row is omitted when the OS has no GPU telemetry.
101
- USE is local NTFS/APFS/HFS fill (no Google Drive, iCloud, or network shares).
101
+ Each local partition (C:, D:, Data, …) gets its own fill bar. No Google Drive, iCloud, or network shares.
102
102
  Disk rates are KiB/s–GiB/s; network rates are kbps/Mbps/Gbps.
103
103
  Disk / net sparks are split (R/W, ↑/↓) and scale to the pair max in the last 60 ticks.
104
104
  Bar fill turns yellow ≥50% and red ≥80%. Unused spark slots use the lowest tick.
package/src/diskuse.js CHANGED
@@ -56,8 +56,29 @@ function systemScore(row) {
56
56
  }
57
57
 
58
58
  /**
59
+ * @param {{ fs?: string, type?: string, mount?: string, size?: number, used?: number, use?: number }} r
60
+ */
61
+ function toVolume(r) {
62
+ const total = Number(r.size) || 0;
63
+ const used = Number(r.used) || 0;
64
+ const percent =
65
+ typeof r.use === "number" && Number.isFinite(r.use)
66
+ ? r.use
67
+ : total > 0
68
+ ? (used / total) * 100
69
+ : 0;
70
+ return {
71
+ percent: Math.min(100, Math.max(0, percent)),
72
+ used,
73
+ total,
74
+ mount: shortMount(r.mount || r.fs || ""),
75
+ };
76
+ }
77
+
78
+ /**
79
+ * One first-class volume per local partition. System disk first, then the rest.
59
80
  * @param {Array<{ fs?: string, type?: string, mount?: string, size?: number, used?: number, use?: number }>} rows
60
- * @returns {{ percent: number, used: number, total: number, mount: string, others: { percent: number, used: number, total: number, mount: string }[] } | null}
81
+ * @returns {{ percent: number, used: number, total: number, mount: string }[] | null}
61
82
  */
62
83
  export function summarizeLocalDisks(rows) {
63
84
  const local = (Array.isArray(rows) ? rows : []).filter(isLocalCapacityVolume);
@@ -73,31 +94,5 @@ export function summarizeLocalDisks(rows) {
73
94
  uniq.push(r);
74
95
  }
75
96
  if (!uniq.length) return null;
76
- const primary = uniq[0];
77
- const total = Number(primary.size) || 0;
78
- const used = Number(primary.used) || 0;
79
- const percent =
80
- typeof primary.use === "number" && Number.isFinite(primary.use)
81
- ? primary.use
82
- : total > 0
83
- ? (used / total) * 100
84
- : 0;
85
- return {
86
- percent: Math.min(100, Math.max(0, percent)),
87
- used,
88
- total,
89
- mount: shortMount(primary.mount || primary.fs || ""),
90
- others: uniq.slice(1).map((r) => {
91
- const t = Number(r.size) || 0;
92
- const u = Number(r.used) || 0;
93
- const p =
94
- typeof r.use === "number" && Number.isFinite(r.use) ? r.use : t > 0 ? (u / t) * 100 : 0;
95
- return {
96
- percent: Math.min(100, Math.max(0, p)),
97
- used: u,
98
- total: t,
99
- mount: shortMount(r.mount || r.fs || ""),
100
- };
101
- }),
102
- };
97
+ return uniq.slice(0, 6).map(toVolume);
103
98
  }
package/src/history.js CHANGED
@@ -9,11 +9,11 @@ import { HISTORY_SIZE } from "./bar.js";
9
9
  * @property {number[]} dskW
10
10
  * @property {number[]} netUp
11
11
  * @property {number[]} netDn
12
- * @property {number[]} diskUse
12
+ * @property {Record<string, number[]>} diskUse
13
13
  */
14
14
 
15
15
  export function createHistory() {
16
- return { cpu: [], ram: [], gpu: [], dskR: [], dskW: [], netUp: [], netDn: [], diskUse: [] };
16
+ return { cpu: [], ram: [], gpu: [], dskR: [], dskW: [], netUp: [], netDn: [], diskUse: {} };
17
17
  }
18
18
 
19
19
  /**
@@ -44,6 +44,19 @@ export function appendHistory(history, snap) {
44
44
  dskW: pushSample(history.dskW, snap.disk?.writeBps),
45
45
  netUp: pushSample(history.netUp, snap.net?.txBps),
46
46
  netDn: pushSample(history.netDn, snap.net?.rxBps),
47
- diskUse: pushSample(history.diskUse, snap.diskUse?.percent),
47
+ diskUse: appendDiskUse(history.diskUse, snap.diskUse),
48
48
  };
49
49
  }
50
+
51
+ /**
52
+ * @param {Record<string, number[]>} prev
53
+ * @param {{ mount: string, percent: number }[] | null | undefined} vols
54
+ */
55
+ function appendDiskUse(prev, vols) {
56
+ /** @type {Record<string, number[]>} */
57
+ const next = { ...prev };
58
+ for (const vol of vols || []) {
59
+ next[vol.mount] = pushSample(next[vol.mount] || [], vol.percent);
60
+ }
61
+ return next;
62
+ }
package/src/render.js CHANGED
@@ -168,19 +168,6 @@ export function renderFrame(snap, history, opts = {}) {
168
168
  }
169
169
  lines.push("");
170
170
 
171
- if (snap.diskUse) {
172
- lines.push(
173
- `${color.green("USE")} ${paintPercentBar(snap.diskUse.percent, color, "green", ascii)} ${formatPercent(snap.diskUse.percent)} ${formatBytePair(snap.diskUse.used, snap.diskUse.total)} ${snap.diskUse.mount}`,
174
- );
175
- lines.push(` ${color.green(sparkline(history.diskUse, sparkW, { ascii, max: 100 }))}`);
176
- for (const extra of snap.diskUse.others || []) {
177
- lines.push(
178
- ` ${extra.mount} ${formatPercent(extra.percent).trim()} ${formatBytePair(extra.used, extra.total)}`,
179
- );
180
- }
181
- }
182
- if (snap.diskUse) lines.push("");
183
-
184
171
  const gpuLines = buildGpuRow(snap.gpu, {
185
172
  history: history.gpu,
186
173
  ascii,
@@ -221,6 +208,19 @@ export function renderFrame(snap, history, opts = {}) {
221
208
  );
222
209
  }
223
210
  lines.push("");
211
+
212
+ if (Array.isArray(snap.diskUse) && snap.diskUse.length) {
213
+ for (const vol of snap.diskUse) {
214
+ const label = vol.mount.length >= 3 ? vol.mount.slice(0, 4) : vol.mount.padEnd(3);
215
+ const spark = history.diskUse?.[vol.mount] || [];
216
+ lines.push(
217
+ `${color.green(label)} ${paintPercentBar(vol.percent, color, "green", ascii)} ${formatPercent(vol.percent)} ${formatBytePair(vol.used, vol.total)}`,
218
+ );
219
+ lines.push(` ${color.green(sparkline(spark, sparkW, { ascii, max: 100 }))}`);
220
+ lines.push("");
221
+ }
222
+ }
223
+
224
224
  lines.push("q quit");
225
225
 
226
226
  return lines.map((ln) => fitLine(ln, columns)).join("\n");
package/src/sample.js CHANGED
@@ -37,7 +37,7 @@ import { rateFromCounters } from "./rates.js";
37
37
  * @property {DiskSample | null} disk
38
38
  * @property {NetSample | null} net
39
39
  * @property {GpuSample | null} gpu
40
- * @property {{ percent: number, used: number, total: number, mount: string, others: { percent: number, used: number, total: number, mount: string }[] } | null} diskUse
40
+ * @property {{ percent: number, used: number, total: number, mount: string }[] | null} diskUse
41
41
  */
42
42
 
43
43
  /**