49 lines
1.5 KiB
TypeScript
49 lines
1.5 KiB
TypeScript
import { spawn } from "node:child_process"
|
|
|
|
export type CommandResult = {
|
|
stdout: string
|
|
stderr: string
|
|
code: number
|
|
}
|
|
|
|
export const commandExists = (command: string) =>
|
|
new Promise<boolean>((resolve) => {
|
|
const child = spawn("sh", ["-lc", `command -v ${command}`])
|
|
child.on("error", () => resolve(false))
|
|
child.on("close", (code) => resolve(code === 0))
|
|
})
|
|
|
|
export const runCommand = (
|
|
command: string,
|
|
args: string[],
|
|
options: { timeoutMs?: number } = {}
|
|
) =>
|
|
new Promise<CommandResult>((resolve, reject) => {
|
|
const child = spawn(command, args, {
|
|
stdio: ["ignore", "pipe", "pipe"],
|
|
})
|
|
|
|
const stdout: Buffer[] = []
|
|
const stderr: Buffer[] = []
|
|
|
|
const timeout = options.timeoutMs
|
|
? setTimeout(() => {
|
|
child.kill("SIGTERM")
|
|
reject(new Error(`${command} wurde nach ${options.timeoutMs} ms beendet`))
|
|
}, options.timeoutMs)
|
|
: null
|
|
|
|
child.stdout.on("data", (chunk) => stdout.push(Buffer.from(chunk)))
|
|
child.stderr.on("data", (chunk) => stderr.push(Buffer.from(chunk)))
|
|
child.on("error", reject)
|
|
child.on("close", (code) => {
|
|
if (timeout) clearTimeout(timeout)
|
|
|
|
resolve({
|
|
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
code: code ?? 0,
|
|
})
|
|
})
|
|
})
|