Files
Termix/src/backend/ssh/widgets/common-utils.ts
T

102 lines
2.3 KiB
TypeScript
Raw Normal View History

2025-11-17 09:46:05 -06:00
import type { Client } from "ssh2";
export function execCommand(
client: Client,
command: string,
+1
2025-12-31 22:20:12 -06:00
timeoutMs = 30000,
2025-11-17 09:46:05 -06:00
): Promise<{
stdout: string;
stderr: string;
code: number | null;
}> {
return new Promise((resolve, reject) => {
+1
2025-12-31 22:20:12 -06:00
let settled = false;
let stream: any = null;
const timeout = setTimeout(() => {
if (!settled) {
settled = true;
cleanup();
reject(new Error(`Command timeout after ${timeoutMs}ms: ${command}`));
}
}, timeoutMs);
const cleanup = () => {
clearTimeout(timeout);
if (stream) {
try {
stream.removeAllListeners();
if (stream.stderr) {
stream.stderr.removeAllListeners();
}
stream.destroy();
} catch (error) {
// Ignore cleanup errors
}
}
};
client.exec(command, { pty: false }, (err, _stream) => {
if (err) {
if (!settled) {
settled = true;
cleanup();
reject(err);
}
return;
}
stream = _stream;
2025-11-17 09:46:05 -06:00
let stdout = "";
let stderr = "";
let exitCode: number | null = null;
+1
2025-12-31 22:20:12 -06:00
2025-11-17 09:46:05 -06:00
stream
.on("close", (code: number | undefined) => {
+1
2025-12-31 22:20:12 -06:00
if (!settled) {
settled = true;
exitCode = typeof code === "number" ? code : null;
cleanup();
resolve({ stdout, stderr, code: exitCode });
}
2025-11-17 09:46:05 -06:00
})
.on("data", (data: Buffer) => {
stdout += data.toString("utf8");
})
+1
2025-12-31 22:20:12 -06:00
.on("error", (streamErr: Error) => {
if (!settled) {
settled = true;
cleanup();
reject(streamErr);
}
2025-11-17 09:46:05 -06:00
});
+1
2025-12-31 22:20:12 -06:00
if (stream.stderr) {
stream.stderr
.on("data", (data: Buffer) => {
stderr += data.toString("utf8");
})
.on("error", (stderrErr: Error) => {
if (!settled) {
settled = true;
cleanup();
reject(stderrErr);
}
});
}
2025-11-17 09:46:05 -06:00
});
});
}
export function toFixedNum(
n: number | null | undefined,
digits = 2,
): number | null {
if (typeof n !== "number" || !Number.isFinite(n)) return null;
return Number(n.toFixed(digits));
}
export function kibToGiB(kib: number): number {
return kib / (1024 * 1024);
}