| import { spawn } from 'node:child_process'; |
| |
| /** @import {SpawnOptions} from 'node:child_process' */ |
| |
| /** |
| * Execute a command |
| * @param {string} command The command to execute |
| * @param {readonly string[]} args The arguments to pass |
| * @param {Omit<SpawnOptions, 'shell'>} [opts] The options to pass to spawnSync |
| * @returns {Promise<string>} The output from the command |
| */ |
| export default async (command, args, opts) => |
| new Promise((resolve, reject) => { |
| const child = spawn(command, args, { ...opts, shell: false }); |
| |
| let stdout = ''; |
| let stderr = ''; |
| |
| if (child.stdout) { |
| child.stdout.setEncoding('utf8'); |
| child.stdout.on('data', (chunk) => { |
| stdout += chunk; |
| }); |
| } |
| |
| if (child.stderr) { |
| child.stderr.setEncoding('utf8'); |
| child.stderr.on('data', (chunk) => { |
| stderr += chunk; |
| }); |
| } |
| |
| child.on('error', (err) => reject(err)); |
| |
| child.on('close', (code) => |
| code == 0 |
| ? resolve(stdout.trim()) |
| : reject( |
| new Error( |
| `The command '${command}' exited with code ${code}: ${stderr.trim()}`, |
| ), |
| ), |
| ); |
| }); |