@glassmkr/crucible 0.13.6 → 0.13.8
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 +1 -1
- package/dist/alerts/state.d.ts +0 -1
- package/dist/alerts/state.js +0 -3
- package/dist/alerts/state.js.map +1 -1
- package/dist/collect/__tests__/cve.test.d.ts +1 -0
- package/dist/collect/__tests__/cve.test.js +29 -0
- package/dist/collect/__tests__/cve.test.js.map +1 -0
- package/dist/collect/conntrack.js +10 -18
- package/dist/collect/conntrack.js.map +1 -1
- package/dist/collect/cve.d.ts +9 -0
- package/dist/collect/cve.js +33 -23
- package/dist/collect/cve.js.map +1 -1
- package/dist/collect/dmesg-events.d.ts +6 -8
- package/dist/collect/dmesg-events.js +8 -26
- package/dist/collect/dmesg-events.js.map +1 -1
- package/dist/collect/dmi.js +7 -16
- package/dist/collect/dmi.js.map +1 -1
- package/dist/collect/edac.js +14 -43
- package/dist/collect/edac.js.map +1 -1
- package/dist/collect/fd.js +4 -12
- package/dist/collect/fd.js.map +1 -1
- package/dist/collect/gpu.d.ts +2 -3
- package/dist/collect/gpu.js +13 -19
- package/dist/collect/gpu.js.map +1 -1
- package/dist/collect/hardware-raid.js +5 -9
- package/dist/collect/hardware-raid.js.map +1 -1
- package/dist/collect/ntp.js +1 -6
- package/dist/collect/ntp.js.map +1 -1
- package/dist/collect/reboot-evidence.js +2 -7
- package/dist/collect/reboot-evidence.js.map +1 -1
- package/dist/collect/softnet.js +7 -15
- package/dist/collect/softnet.js.map +1 -1
- package/dist/collect/systemd.d.ts +8 -1
- package/dist/collect/systemd.js +12 -31
- package/dist/collect/systemd.js.map +1 -1
- package/dist/collect/tcp-stats.js +16 -49
- package/dist/collect/tcp-stats.js.map +1 -1
- package/dist/collect/thermal.js +9 -14
- package/dist/collect/thermal.js.map +1 -1
- package/dist/collect/zfs.js +2 -3
- package/dist/collect/zfs.js.map +1 -1
- package/dist/lib/__tests__/dmesg.test.d.ts +1 -0
- package/dist/lib/__tests__/dmesg.test.js +87 -0
- package/dist/lib/__tests__/dmesg.test.js.map +1 -0
- package/dist/lib/__tests__/exec.test.js +16 -1
- package/dist/lib/__tests__/exec.test.js.map +1 -1
- package/dist/lib/__tests__/parse.test.js +111 -2
- package/dist/lib/__tests__/parse.test.js.map +1 -1
- package/dist/lib/__tests__/rate.test.d.ts +1 -0
- package/dist/lib/__tests__/rate.test.js +67 -0
- package/dist/lib/__tests__/rate.test.js.map +1 -0
- package/dist/lib/dmesg.d.ts +29 -0
- package/dist/lib/dmesg.js +56 -0
- package/dist/lib/dmesg.js.map +1 -0
- package/dist/lib/exec.d.ts +2 -0
- package/dist/lib/exec.js +14 -0
- package/dist/lib/exec.js.map +1 -1
- package/dist/lib/parse.d.ts +5 -0
- package/dist/lib/parse.js +84 -1
- package/dist/lib/parse.js.map +1 -1
- package/dist/lib/rate.d.ts +12 -0
- package/dist/lib/rate.js +52 -0
- package/dist/lib/rate.js.map +1 -0
- package/dist/lib/version-check.d.ts +0 -6
- package/dist/lib/version-check.js +0 -11
- package/dist/lib/version-check.js.map +1 -1
- package/dist/metrics-server.js +0 -1
- package/dist/metrics-server.js.map +1 -1
- package/package.json +1 -1
package/dist/collect/thermal.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { isCpuChip } from "../lib/cpu-thermal-chips.js";
|
|
4
|
+
import { readFileTrim } from "../lib/parse.js";
|
|
4
5
|
const HWMON_ROOT = "/sys/class/hwmon";
|
|
5
6
|
const THERMAL_ZONE_ROOT = "/sys/class/thermal";
|
|
6
7
|
// Driver names we skip entirely (not in cpu_readings, not in other_readings).
|
|
@@ -9,15 +10,9 @@ const THERMAL_ZONE_ROOT = "/sys/class/thermal";
|
|
|
9
10
|
const SKIP_CHIPS = new Set([
|
|
10
11
|
"nvme", // already covered by SMART
|
|
11
12
|
]);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return raw.trim();
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
13
|
+
// listDir intentionally returns null (not []) on error so collectThermal
|
|
14
|
+
// can distinguish "looked but empty" from "couldn't look at all" (see the
|
|
15
|
+
// everLookedAt* logic below); readDirSafe's [] return would conflate them.
|
|
21
16
|
async function listDir(path) {
|
|
22
17
|
try {
|
|
23
18
|
return await fs.readdir(path);
|
|
@@ -97,7 +92,7 @@ export async function collectFromHwmon(root = HWMON_ROOT) {
|
|
|
97
92
|
const other = [];
|
|
98
93
|
for (const entry of entries) {
|
|
99
94
|
const chipDir = join(root, entry);
|
|
100
|
-
const chipName =
|
|
95
|
+
const chipName = readFileTrim(join(chipDir, "name"));
|
|
101
96
|
if (!chipName)
|
|
102
97
|
continue;
|
|
103
98
|
if (SKIP_CHIPS.has(chipName))
|
|
@@ -115,7 +110,7 @@ export async function collectFromHwmon(root = HWMON_ROOT) {
|
|
|
115
110
|
const chipReadings = [];
|
|
116
111
|
for (const inputFile of tempInputs) {
|
|
117
112
|
const idx = inputFile.match(/^temp(\d+)_input$/)[1];
|
|
118
|
-
const valueRaw =
|
|
113
|
+
const valueRaw = readFileTrim(join(chipDir, inputFile));
|
|
119
114
|
if (!valueRaw)
|
|
120
115
|
continue;
|
|
121
116
|
const millideg = parseInt(valueRaw, 10);
|
|
@@ -125,7 +120,7 @@ export async function collectFromHwmon(root = HWMON_ROOT) {
|
|
|
125
120
|
// Reject obviously bogus values (millideg out of range / sensor offline)
|
|
126
121
|
if (celsius < -50 || celsius > 200)
|
|
127
122
|
continue;
|
|
128
|
-
const labelFile =
|
|
123
|
+
const labelFile = readFileTrim(join(chipDir, `temp${idx}_label`));
|
|
129
124
|
const label = labelFile ? `${chipName} ${labelFile}` : `${chipName} temp${idx}`;
|
|
130
125
|
const reading = {
|
|
131
126
|
label,
|
|
@@ -167,8 +162,8 @@ export async function collectFromThermalZone(root = THERMAL_ZONE_ROOT) {
|
|
|
167
162
|
if (!entry.startsWith("thermal_zone"))
|
|
168
163
|
continue;
|
|
169
164
|
const zoneDir = join(root, entry);
|
|
170
|
-
const type =
|
|
171
|
-
const tempRaw =
|
|
165
|
+
const type = readFileTrim(join(zoneDir, "type"));
|
|
166
|
+
const tempRaw = readFileTrim(join(zoneDir, "temp"));
|
|
172
167
|
if (!type || !tempRaw)
|
|
173
168
|
continue;
|
|
174
169
|
const millideg = parseInt(tempRaw, 10);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thermal.js","sourceRoot":"","sources":["../../src/collect/thermal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"thermal.js","sourceRoot":"","sources":["../../src/collect/thermal.ts"],"names":[],"mappings":"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"}
|
package/dist/collect/zfs.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { run } from "../lib/exec.js";
|
|
1
|
+
import { run, which } from "../lib/exec.js";
|
|
2
2
|
export async function collectZfs() {
|
|
3
3
|
// Check if zpool is installed
|
|
4
|
-
|
|
5
|
-
if (!zpoolPath || !zpoolPath.trim())
|
|
4
|
+
if (!(await which("zpool", 3000)))
|
|
6
5
|
return null;
|
|
7
6
|
const zpoolStatus = await run("zpool", ["status"], 10000);
|
|
8
7
|
if (!zpoolStatus || !zpoolStatus.trim())
|
package/dist/collect/zfs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zfs.js","sourceRoot":"","sources":["../../src/collect/zfs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"zfs.js","sourceRoot":"","sources":["../../src/collect/zfs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Tests for the shared lib/dmesg read + timestamp parser.
|
|
2
|
+
//
|
|
3
|
+
// readDmesg is exercised with a mocked lib/exec `run` so we can assert
|
|
4
|
+
// the two-step argv (iso attempt, then plain fallback) and the
|
|
5
|
+
// fall-back-on-empty behaviour both collectors relied on.
|
|
6
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
7
|
+
const runMock = vi.fn();
|
|
8
|
+
vi.mock("../exec.js", () => ({
|
|
9
|
+
run: (...args) => runMock(...args),
|
|
10
|
+
}));
|
|
11
|
+
const { readDmesg, parseKernelLogTimestamp } = await import("../dmesg.js");
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
runMock.mockReset();
|
|
14
|
+
});
|
|
15
|
+
describe("readDmesg", () => {
|
|
16
|
+
it("returns the iso-attempt output when it succeeds (no fallback call)", async () => {
|
|
17
|
+
runMock.mockResolvedValueOnce("iso line\n");
|
|
18
|
+
const out = await readDmesg();
|
|
19
|
+
expect(out).toBe("iso line\n");
|
|
20
|
+
expect(runMock).toHaveBeenCalledTimes(1);
|
|
21
|
+
expect(runMock.mock.calls[0][0]).toBe("dmesg");
|
|
22
|
+
expect(runMock.mock.calls[0][1]).toEqual(["--time-format=iso", "--no-pager"]);
|
|
23
|
+
});
|
|
24
|
+
it("appends extraIsoArgs to the iso attempt only", async () => {
|
|
25
|
+
runMock.mockResolvedValueOnce("iso line\n");
|
|
26
|
+
await readDmesg({ extraIsoArgs: ["--ctime"] });
|
|
27
|
+
expect(runMock.mock.calls[0][1]).toEqual(["--time-format=iso", "--no-pager", "--ctime"]);
|
|
28
|
+
});
|
|
29
|
+
it("falls back to plain --no-pager when the iso attempt is null", async () => {
|
|
30
|
+
runMock.mockResolvedValueOnce(null);
|
|
31
|
+
runMock.mockResolvedValueOnce("plain line\n");
|
|
32
|
+
const out = await readDmesg();
|
|
33
|
+
expect(out).toBe("plain line\n");
|
|
34
|
+
expect(runMock).toHaveBeenCalledTimes(2);
|
|
35
|
+
expect(runMock.mock.calls[1][1]).toEqual(["--no-pager"]);
|
|
36
|
+
});
|
|
37
|
+
it("falls back when the iso attempt is an empty string", async () => {
|
|
38
|
+
runMock.mockResolvedValueOnce("");
|
|
39
|
+
runMock.mockResolvedValueOnce("plain line\n");
|
|
40
|
+
const out = await readDmesg();
|
|
41
|
+
expect(out).toBe("plain line\n");
|
|
42
|
+
expect(runMock).toHaveBeenCalledTimes(2);
|
|
43
|
+
});
|
|
44
|
+
it("returns null when both attempts produce nothing", async () => {
|
|
45
|
+
runMock.mockResolvedValueOnce(null);
|
|
46
|
+
runMock.mockResolvedValueOnce(null);
|
|
47
|
+
expect(await readDmesg()).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
it("threads timeoutMs through to both run calls", async () => {
|
|
50
|
+
runMock.mockResolvedValueOnce(null);
|
|
51
|
+
runMock.mockResolvedValueOnce(null);
|
|
52
|
+
await readDmesg({ timeoutMs: 5000 });
|
|
53
|
+
expect(runMock.mock.calls[0][2]).toBe(5000);
|
|
54
|
+
expect(runMock.mock.calls[1][2]).toBe(5000);
|
|
55
|
+
});
|
|
56
|
+
it("omits the timeout arg entirely when timeoutMs is unset (run's default applies)", async () => {
|
|
57
|
+
runMock.mockResolvedValueOnce("x\n");
|
|
58
|
+
await readDmesg();
|
|
59
|
+
// run was called with exactly (cmd, args) — no third positional.
|
|
60
|
+
expect(runMock.mock.calls[0].length).toBe(2);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("parseKernelLogTimestamp", () => {
|
|
64
|
+
it("parses ISO format with comma fractional seconds and timezone", () => {
|
|
65
|
+
const ts = parseKernelLogTimestamp("2026-05-19T12:34:56,789012+00:00 some message");
|
|
66
|
+
expect(ts).not.toBeNull();
|
|
67
|
+
expect(typeof ts).toBe("number");
|
|
68
|
+
// comma-normalised-to-dot must parse to the same instant as the dot form
|
|
69
|
+
expect(ts).toBe(Date.parse("2026-05-19T12:34:56.789012+00:00"));
|
|
70
|
+
});
|
|
71
|
+
it("parses ISO format with Z suffix", () => {
|
|
72
|
+
const ts = parseKernelLogTimestamp("2026-05-19T12:34:56Z kernel: hi");
|
|
73
|
+
expect(ts).toBe(Date.parse("2026-05-19T12:34:56Z"));
|
|
74
|
+
});
|
|
75
|
+
it("parses ctime format from --ctime", () => {
|
|
76
|
+
const ts = parseKernelLogTimestamp("[Mon May 19 12:34:56 2026] some message");
|
|
77
|
+
expect(ts).not.toBeNull();
|
|
78
|
+
expect(ts).toBe(Date.parse("Mon May 19 12:34:56 2026"));
|
|
79
|
+
});
|
|
80
|
+
it("returns null for relative-time format", () => {
|
|
81
|
+
expect(parseKernelLogTimestamp("[12345.678] some message")).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
it("returns null for a line with no leading timestamp", () => {
|
|
84
|
+
expect(parseKernelLogTimestamp("no timestamp here")).toBeNull();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=dmesg.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dmesg.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/dmesg.test.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,uEAAuE;AACvE,+DAA+D;AAC/D,0DAA0D;AAE1D,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE9D,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AACxB,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3B,GAAG,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9C,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,SAAS,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;AAE3E,UAAU,CAAC,GAAG,EAAE;IACd,OAAO,CAAC,SAAS,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAClF,OAAO,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,OAAO,CAAC,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAClC,OAAO,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAC9F,OAAO,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,SAAS,EAAE,CAAC;QAClB,iEAAiE;QACjE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,EAAE,GAAG,uBAAuB,CAAC,+CAA+C,CAAC,CAAC;QACpF,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,yEAAyE;QACzE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,EAAE,GAAG,uBAAuB,CAAC,iCAAiC,CAAC,CAAC;QACtE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,EAAE,GAAG,uBAAuB,CAAC,yCAAyC,CAAC,CAAC;QAC9E,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,uBAAuB,CAAC,0BAA0B,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,CAAC,uBAAuB,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { run, runDetailed, looksLikeFieldRenameError } from "../exec.js";
|
|
2
|
+
import { run, runDetailed, looksLikeFieldRenameError, which, isUnitActive } from "../exec.js";
|
|
3
3
|
describe("looksLikeFieldRenameError", () => {
|
|
4
4
|
// Real-world fixtures from the two Crucible bugs that motivated this
|
|
5
5
|
// defense. If the heuristic stops recognising these strings, the next
|
|
@@ -70,4 +70,19 @@ describe("run (backwards-compat shim)", () => {
|
|
|
70
70
|
expect(out?.trim()).toBe("hi");
|
|
71
71
|
});
|
|
72
72
|
});
|
|
73
|
+
describe("which", () => {
|
|
74
|
+
it("returns true for a binary on PATH", async () => {
|
|
75
|
+
expect(await which("sh")).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
it("returns false for a binary not on PATH", async () => {
|
|
78
|
+
expect(await which("definitely-not-a-real-binary-9j43k")).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("isUnitActive", () => {
|
|
82
|
+
// A unit that is not active (or a host without systemd, where the
|
|
83
|
+
// systemctl ENOENT path resolves to "not active") returns false.
|
|
84
|
+
it("returns false for a non-active / missing unit", async () => {
|
|
85
|
+
expect(await isUnitActive("crucible-nonexistent-9j43k.service")).toBe(false);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
73
88
|
//# sourceMappingURL=exec.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/exec.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"exec.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/exec.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
1
|
+
import { afterAll, beforeAll, describe, it, expect } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "fs";
|
|
3
|
+
import { tmpdir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { parseColumnarStat, parseEqualsKeyValue, parseKeyValue, parseKb, readDirSafe, readFileInt, readFileTrim, } from "../parse.js";
|
|
3
6
|
describe("parseKeyValue", () => {
|
|
4
7
|
it("parses colon-delimited key/value lines", () => {
|
|
5
8
|
const out = parseKeyValue("Name: foo\nVersion: 1.2.3\n");
|
|
@@ -12,6 +15,67 @@ describe("parseKeyValue", () => {
|
|
|
12
15
|
expect(parseKeyValue(" A : 1 \n")).toEqual({ A: "1" });
|
|
13
16
|
});
|
|
14
17
|
});
|
|
18
|
+
describe("parseEqualsKeyValue", () => {
|
|
19
|
+
it("parses equals-delimited key/value lines (systemctl show shape)", () => {
|
|
20
|
+
const out = parseEqualsKeyValue("Result=exit-code\nActiveState=failed\nSubState=failed\nNRestarts=2");
|
|
21
|
+
expect(out).toEqual({
|
|
22
|
+
Result: "exit-code",
|
|
23
|
+
ActiveState: "failed",
|
|
24
|
+
SubState: "failed",
|
|
25
|
+
NRestarts: "2",
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
it("ignores lines with no equals sign", () => {
|
|
29
|
+
expect(parseEqualsKeyValue("no equals here\nA=1\n")).toEqual({ A: "1" });
|
|
30
|
+
});
|
|
31
|
+
it("trims whitespace around keys and values", () => {
|
|
32
|
+
expect(parseEqualsKeyValue(" A = 1 \n")).toEqual({ A: "1" });
|
|
33
|
+
});
|
|
34
|
+
it("splits on the first equals so values may contain equals", () => {
|
|
35
|
+
expect(parseEqualsKeyValue("ExecStart=/bin/sh -c x=1")).toEqual({
|
|
36
|
+
ExecStart: "/bin/sh -c x=1",
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
it("returns {} for empty input", () => {
|
|
40
|
+
expect(parseEqualsKeyValue("")).toEqual({});
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("parseColumnarStat", () => {
|
|
44
|
+
// Shape of /proc/net/snmp's Tcp: section.
|
|
45
|
+
const snmp = "Tcp: RtoAlgorithm RtoMin InSegs OutSegs RetransSegs\n" +
|
|
46
|
+
"Tcp: 1 200 9876543 8765432 1234\n";
|
|
47
|
+
it("extracts requested columns from the header+value rows", () => {
|
|
48
|
+
expect(parseColumnarStat(snmp, "Tcp:", ["InSegs", "OutSegs", "RetransSegs"])).toEqual({
|
|
49
|
+
InSegs: 9876543,
|
|
50
|
+
OutSegs: 8765432,
|
|
51
|
+
RetransSegs: 1234,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
it("ignores other prefixed sections in the same file", () => {
|
|
55
|
+
const mixed = "Ip: Forwarding DefaultTTL\nIp: 1 64\n" + snmp + "Udp: InDatagrams\nUdp: 5\n";
|
|
56
|
+
expect(parseColumnarStat(mixed, "Tcp:", ["InSegs"])).toEqual({ InSegs: 9876543 });
|
|
57
|
+
});
|
|
58
|
+
it("returns null when the section is absent", () => {
|
|
59
|
+
expect(parseColumnarStat("Ip: Forwarding\nIp: 1\n", "Tcp:", ["InSegs"])).toBeNull();
|
|
60
|
+
});
|
|
61
|
+
it("returns null when only the header row is present (no value row)", () => {
|
|
62
|
+
expect(parseColumnarStat("Tcp: InSegs OutSegs\n", "Tcp:", ["InSegs"])).toBeNull();
|
|
63
|
+
});
|
|
64
|
+
it("returns null when a requested column is missing from the header", () => {
|
|
65
|
+
expect(parseColumnarStat(snmp, "Tcp:", ["InSegs", "Nope"])).toBeNull();
|
|
66
|
+
});
|
|
67
|
+
it("returns null when a requested value is non-numeric", () => {
|
|
68
|
+
const bad = "Tcp: InSegs OutSegs\nTcp: 100 notanumber\n";
|
|
69
|
+
expect(parseColumnarStat(bad, "Tcp:", ["OutSegs"])).toBeNull();
|
|
70
|
+
});
|
|
71
|
+
it("strips the prefix token before splitting (longer prefix)", () => {
|
|
72
|
+
const ext = "TcpExt: ListenOverflows ListenDrops\nTcpExt: 7 3\n";
|
|
73
|
+
expect(parseColumnarStat(ext, "TcpExt:", ["ListenOverflows", "ListenDrops"])).toEqual({
|
|
74
|
+
ListenOverflows: 7,
|
|
75
|
+
ListenDrops: 3,
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
15
79
|
describe("parseKb", () => {
|
|
16
80
|
it("parses a numeric kB value", () => {
|
|
17
81
|
expect(parseKb("16384 kB")).toBe(16384);
|
|
@@ -24,4 +88,49 @@ describe("parseKb", () => {
|
|
|
24
88
|
expect(parseKb("not a number")).toBe(0);
|
|
25
89
|
});
|
|
26
90
|
});
|
|
91
|
+
describe("file-read helpers", () => {
|
|
92
|
+
let dir;
|
|
93
|
+
beforeAll(() => {
|
|
94
|
+
dir = mkdtempSync(join(tmpdir(), "crucible-parse-"));
|
|
95
|
+
writeFileSync(join(dir, "value"), " 42\n");
|
|
96
|
+
writeFileSync(join(dir, "text"), " hello world \n");
|
|
97
|
+
writeFileSync(join(dir, "empty"), " \n");
|
|
98
|
+
writeFileSync(join(dir, "notint"), "12x\n");
|
|
99
|
+
});
|
|
100
|
+
afterAll(() => {
|
|
101
|
+
rmSync(dir, { recursive: true, force: true });
|
|
102
|
+
});
|
|
103
|
+
describe("readFileTrim", () => {
|
|
104
|
+
it("returns trimmed contents", () => {
|
|
105
|
+
expect(readFileTrim(join(dir, "text"))).toBe("hello world");
|
|
106
|
+
});
|
|
107
|
+
it("returns empty string (not null) for whitespace-only files", () => {
|
|
108
|
+
expect(readFileTrim(join(dir, "empty"))).toBe("");
|
|
109
|
+
});
|
|
110
|
+
it("returns null when the file does not exist", () => {
|
|
111
|
+
expect(readFileTrim(join(dir, "nope"))).toBeNull();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("readFileInt", () => {
|
|
115
|
+
it("parses a non-negative integer", () => {
|
|
116
|
+
expect(readFileInt(join(dir, "value"))).toBe(42);
|
|
117
|
+
});
|
|
118
|
+
it("returns null for non-integer contents", () => {
|
|
119
|
+
expect(readFileInt(join(dir, "notint"))).toBeNull();
|
|
120
|
+
expect(readFileInt(join(dir, "text"))).toBeNull();
|
|
121
|
+
expect(readFileInt(join(dir, "empty"))).toBeNull();
|
|
122
|
+
});
|
|
123
|
+
it("returns null when the file does not exist", () => {
|
|
124
|
+
expect(readFileInt(join(dir, "nope"))).toBeNull();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
describe("readDirSafe", () => {
|
|
128
|
+
it("lists directory entries", () => {
|
|
129
|
+
expect(readDirSafe(dir).sort()).toEqual(["empty", "notint", "text", "value"]);
|
|
130
|
+
});
|
|
131
|
+
it("returns [] for a missing directory", () => {
|
|
132
|
+
expect(readDirSafe(join(dir, "nope"))).toEqual([]);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
27
136
|
//# sourceMappingURL=parse.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/parse.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/parse.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,OAAO,EACP,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,GAAG,GAAG,aAAa,CAAC,6BAA6B,CAAC,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,CAAC,aAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,GAAG,GAAG,mBAAmB,CAC7B,oEAAoE,CACrE,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YAClB,MAAM,EAAE,WAAW;YACnB,WAAW,EAAE,QAAQ;YACrB,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,mBAAmB,CAAC,uBAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,mBAAmB,CAAC,0BAA0B,CAAC,CAAC,CAAC,OAAO,CAAC;YAC9D,SAAS,EAAE,gBAAgB;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,0CAA0C;IAC1C,MAAM,IAAI,GACR,uDAAuD;QACvD,mCAAmC,CAAC;IAEtC,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACpF,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,KAAK,GACT,uCAAuC,GAAG,IAAI,GAAG,4BAA4B,CAAC;QAChF,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,iBAAiB,CAAC,yBAAyB,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACtF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,iBAAiB,CAAC,uBAAuB,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACpF,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,GAAG,GAAG,4CAA4C,CAAC;QACzD,MAAM,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,GAAG,GACP,oDAAoD,CAAC;QACvD,MAAM,CAAC,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YACpF,eAAe,EAAE,CAAC;YAClB,WAAW,EAAE,CAAC;SACf,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,IAAI,GAAW,CAAC;IAChB,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACrD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC5C,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACtD,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QAC3C,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,EAAE;QACZ,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;QAC5B,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;YACvC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YACpD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YAClD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACrD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;QAC3B,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;YACjC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
2
|
+
import { RateTracker } from "../rate.js";
|
|
3
|
+
describe("RateTracker.computeRate", () => {
|
|
4
|
+
let r;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
r = new RateTracker();
|
|
7
|
+
});
|
|
8
|
+
it("returns null on the first observation of a key (no baseline)", () => {
|
|
9
|
+
expect(r.computeRate("c", 100, 1000)).toBeNull();
|
|
10
|
+
});
|
|
11
|
+
it("computes per-second rate from a normal positive delta", () => {
|
|
12
|
+
expect(r.computeRate("c", 100, 1000)).toBeNull(); // baseline
|
|
13
|
+
// +50 counts over 2 seconds = 25/s
|
|
14
|
+
expect(r.computeRate("c", 150, 3000)).toBe(25);
|
|
15
|
+
});
|
|
16
|
+
it("computes a fractional rate", () => {
|
|
17
|
+
r.computeRate("c", 0, 0);
|
|
18
|
+
// +1 over 0.5s = 2/s
|
|
19
|
+
expect(r.computeRate("c", 1, 500)).toBe(2);
|
|
20
|
+
});
|
|
21
|
+
it("returns 0 for a zero delta over a positive interval", () => {
|
|
22
|
+
r.computeRate("c", 100, 1000);
|
|
23
|
+
expect(r.computeRate("c", 100, 2000)).toBe(0);
|
|
24
|
+
});
|
|
25
|
+
it("returns null and rebaselines on a counter reset (negative delta)", () => {
|
|
26
|
+
r.computeRate("c", 100, 1000);
|
|
27
|
+
// Counter went backwards (reboot / rollover): null this tick.
|
|
28
|
+
expect(r.computeRate("c", 10, 2000)).toBeNull();
|
|
29
|
+
// ...and the baseline is now the post-reset value, so the next tick
|
|
30
|
+
// rates against 10, not 100. +20 over 1s = 20/s.
|
|
31
|
+
expect(r.computeRate("c", 30, 3000)).toBe(20);
|
|
32
|
+
});
|
|
33
|
+
it("returns null for a zero elapsed interval but still rebaselines the value", () => {
|
|
34
|
+
r.computeRate("c", 100, 1000);
|
|
35
|
+
// Same instant: elapsedSec == 0 -> null (no divide).
|
|
36
|
+
expect(r.computeRate("c", 200, 1000)).toBeNull();
|
|
37
|
+
// Baseline value advanced to 200 at t=1000; next tick rates against
|
|
38
|
+
// 200. +50 over 1s = 50/s.
|
|
39
|
+
expect(r.computeRate("c", 250, 2000)).toBe(50);
|
|
40
|
+
});
|
|
41
|
+
it("returns null for a negative elapsed interval (clock went backwards)", () => {
|
|
42
|
+
r.computeRate("c", 100, 2000);
|
|
43
|
+
expect(r.computeRate("c", 200, 1000)).toBeNull();
|
|
44
|
+
});
|
|
45
|
+
it("tracks multiple keys independently", () => {
|
|
46
|
+
r.computeRate("a", 100, 1000);
|
|
47
|
+
r.computeRate("b", 200, 1000);
|
|
48
|
+
// a: +10/1s = 10; b: +40/1s = 40. Same nowMs (callers share one
|
|
49
|
+
// capture instant for counters that must advance together).
|
|
50
|
+
expect(r.computeRate("a", 110, 2000)).toBe(10);
|
|
51
|
+
expect(r.computeRate("b", 240, 2000)).toBe(40);
|
|
52
|
+
});
|
|
53
|
+
it("does not let one key's reset affect another key", () => {
|
|
54
|
+
r.computeRate("a", 100, 1000);
|
|
55
|
+
r.computeRate("b", 100, 1000);
|
|
56
|
+
expect(r.computeRate("a", 50, 2000)).toBeNull(); // a reset
|
|
57
|
+
expect(r.computeRate("b", 150, 2000)).toBe(50); // b unaffected
|
|
58
|
+
});
|
|
59
|
+
it("reset() drops all baselines so the next call is treated as first", () => {
|
|
60
|
+
r.computeRate("c", 100, 1000);
|
|
61
|
+
r.reset();
|
|
62
|
+
expect(r.computeRate("c", 150, 2000)).toBeNull();
|
|
63
|
+
// And tracking resumes from the new baseline.
|
|
64
|
+
expect(r.computeRate("c", 200, 3000)).toBe(50);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=rate.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/rate.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,IAAI,CAAc,CAAC;IACnB,UAAU,CAAC,GAAG,EAAE;QACd,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,WAAW;QAC7D,mCAAmC;QACnC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACzB,qBAAqB;QACrB,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,8DAA8D;QAC9D,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAChD,oEAAoE;QACpE,iDAAiD;QACjD,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,qDAAqD;QACrD,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjD,oEAAoE;QACpE,2BAA2B;QAC3B,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,gEAAgE;QAChE,4DAA4D;QAC5D,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU;QAC3D,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjD,8CAA8C;QAC9C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface ReadDmesgOptions {
|
|
2
|
+
/** Per-call timeout passed to `run`. dmesg-events uses run's default
|
|
3
|
+
* (10s); the gpu collector uses its 5s nvidia-smi budget. */
|
|
4
|
+
timeoutMs?: number;
|
|
5
|
+
/** Extra args appended to the FIRST (iso) attempt only. dmesg-events
|
|
6
|
+
* passes `--ctime`; the gpu collector passes nothing. Kept verbatim
|
|
7
|
+
* so each call site's argv is preserved exactly. */
|
|
8
|
+
extraIsoArgs?: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Read the kernel ring buffer. Returns the raw dmesg text, or null when
|
|
12
|
+
* dmesg is missing / not readable (CAP_SYSLOG absent or
|
|
13
|
+
* kernel.dmesg_restrict=1).
|
|
14
|
+
*
|
|
15
|
+
* Two-step, preserving the historical behavior of both callers:
|
|
16
|
+
* 1. `dmesg --time-format=iso --no-pager [extraIsoArgs...]`
|
|
17
|
+
* 2. on a null/empty result, `dmesg --no-pager`
|
|
18
|
+
*/
|
|
19
|
+
export declare function readDmesg(opts?: ReadDmesgOptions): Promise<string | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Extract a unix-ms timestamp from a dmesg line. Two absolute shapes:
|
|
22
|
+
* ISO: "2026-05-19T12:34:56,789012+00:00 ..." (--time-format=iso)
|
|
23
|
+
* ctime: "[Mon May 19 12:34:56 2026] ..." (--ctime)
|
|
24
|
+
*
|
|
25
|
+
* Relative-time format ("[12345.678]") returns null (no absolute anchor
|
|
26
|
+
* available without uptime). The comma fractional separator that iso
|
|
27
|
+
* format emits is normalised to a dot before Date.parse.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseKernelLogTimestamp(line: string): number | null;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Shared dmesg read + kernel-log timestamp parsing.
|
|
2
|
+
//
|
|
3
|
+
// Both the dmesg-events collector (C18) and the gpu collector's XID
|
|
4
|
+
// scan read the kernel ring buffer the same way: try `--time-format=iso`
|
|
5
|
+
// (kernel 5.10+) first, fall back to plain `--no-pager` when that call
|
|
6
|
+
// produces nothing (older kernels ignore the flag; missing privileges
|
|
7
|
+
// is the more common cause). They also parse the leading timestamp the
|
|
8
|
+
// same way. This module hosts the shared read + parse so the two
|
|
9
|
+
// collectors don't drift.
|
|
10
|
+
import { run } from "./exec.js";
|
|
11
|
+
/**
|
|
12
|
+
* Read the kernel ring buffer. Returns the raw dmesg text, or null when
|
|
13
|
+
* dmesg is missing / not readable (CAP_SYSLOG absent or
|
|
14
|
+
* kernel.dmesg_restrict=1).
|
|
15
|
+
*
|
|
16
|
+
* Two-step, preserving the historical behavior of both callers:
|
|
17
|
+
* 1. `dmesg --time-format=iso --no-pager [extraIsoArgs...]`
|
|
18
|
+
* 2. on a null/empty result, `dmesg --no-pager`
|
|
19
|
+
*/
|
|
20
|
+
export async function readDmesg(opts = {}) {
|
|
21
|
+
const { timeoutMs, extraIsoArgs = [] } = opts;
|
|
22
|
+
const isoArgs = ["--time-format=iso", "--no-pager", ...extraIsoArgs];
|
|
23
|
+
const first = timeoutMs === undefined
|
|
24
|
+
? await run("dmesg", isoArgs)
|
|
25
|
+
: await run("dmesg", isoArgs, timeoutMs);
|
|
26
|
+
if (first)
|
|
27
|
+
return first;
|
|
28
|
+
return timeoutMs === undefined
|
|
29
|
+
? await run("dmesg", ["--no-pager"])
|
|
30
|
+
: await run("dmesg", ["--no-pager"], timeoutMs);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extract a unix-ms timestamp from a dmesg line. Two absolute shapes:
|
|
34
|
+
* ISO: "2026-05-19T12:34:56,789012+00:00 ..." (--time-format=iso)
|
|
35
|
+
* ctime: "[Mon May 19 12:34:56 2026] ..." (--ctime)
|
|
36
|
+
*
|
|
37
|
+
* Relative-time format ("[12345.678]") returns null (no absolute anchor
|
|
38
|
+
* available without uptime). The comma fractional separator that iso
|
|
39
|
+
* format emits is normalised to a dot before Date.parse.
|
|
40
|
+
*/
|
|
41
|
+
export function parseKernelLogTimestamp(line) {
|
|
42
|
+
const isoMatch = line.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:[,.]\d+)?(?:[+-]\d{2}:?\d{2}|Z)?)/);
|
|
43
|
+
if (isoMatch) {
|
|
44
|
+
// Normalise the comma fractional separator to dot.
|
|
45
|
+
const iso = isoMatch[1].replace(",", ".");
|
|
46
|
+
const t = Date.parse(iso);
|
|
47
|
+
return Number.isFinite(t) ? t : null;
|
|
48
|
+
}
|
|
49
|
+
const ctimeMatch = line.match(/^\[([A-Z][a-z]{2}\s+[A-Z][a-z]{2}\s+\d+\s+\d{2}:\d{2}:\d{2}\s+\d{4})\]/);
|
|
50
|
+
if (ctimeMatch) {
|
|
51
|
+
const t = Date.parse(ctimeMatch[1]);
|
|
52
|
+
return Number.isFinite(t) ? t : null;
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=dmesg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dmesg.js","sourceRoot":"","sources":["../../src/lib/dmesg.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,oEAAoE;AACpE,yEAAyE;AACzE,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,iEAAiE;AACjE,0BAA0B;AAE1B,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAYhC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAyB,EAAE;IACzD,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC;IAC9C,MAAM,OAAO,GAAG,CAAC,mBAAmB,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,CAAC;IACrE,MAAM,KAAK,GACT,SAAS,KAAK,SAAS;QACrB,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;QAC7B,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC7C,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO,SAAS,KAAK,SAAS;QAC5B,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC;QACpC,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,2EAA2E,CAC5E,CAAC;IACF,IAAI,QAAQ,EAAE,CAAC;QACb,mDAAmD;QACnD,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAC3B,wEAAwE,CACzE,CAAC;IACF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/lib/exec.d.ts
CHANGED
|
@@ -7,4 +7,6 @@ export interface RunDetailedResult {
|
|
|
7
7
|
timedOut: boolean;
|
|
8
8
|
}
|
|
9
9
|
export declare function runDetailed(cmd: string, args: string[], timeoutMs?: number): Promise<RunDetailedResult>;
|
|
10
|
+
export declare function which(name: string, timeoutMs?: number): Promise<boolean>;
|
|
11
|
+
export declare function isUnitActive(unit: string, timeoutMs?: number): Promise<boolean>;
|
|
10
12
|
export declare function looksLikeFieldRenameError(stderr: string): boolean;
|