@nu-art/commando
Version:
Shell command execution framework with interactive sessions, CLI parameter resolution, and plugin system for building and executing shell scripts programmatically
96 lines (95 loc) • 3.46 kB
JavaScript
/*
* commando provides shell command execution framework with interactive sessions and plugin system
*
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { exec } from 'child_process';
import { Logger } from '@nu-art/ts-common';
import { CliError } from '../core/CliError.js';
/**
* Converts input to string, handling Buffer and ArrayBufferLike types.
*
* @param input - String, Buffer, or ArrayBufferLike to convert
* @returns UTF-8 string representation
*/
function toStringWithNewlines(input) {
if (typeof input === 'string')
return input;
return Buffer.isBuffer(input)
? input.toString('utf8')
: Buffer.from(input).toString('utf8');
}
/**
* Simple shell command executor using Node.js child_process.
*
* Executes shell commands synchronously via `exec()` and handles
* output conversion. Supports debug logging and custom shell/options.
*
* **Behavior**:
* - Uses `/bin/bash` as default shell
* - Converts Buffer output to UTF-8 strings
* - Logs stdout as info, stderr as error
* - Throws CliError on command failure
* - Supports UID tagging for log identification
*/
export class SimpleShell extends Logger {
/** Debug mode flag (enables verbose command logging) */
_debug = false;
/** Execution options for child_process.exec() */
cliOptions = { shell: '/bin/bash' };
/**
* Executes a shell command and returns stdout/stderr.
*
* **Behavior**:
* - Logs command in debug mode (wrapped in triple quotes)
* - Converts Buffer output to UTF-8 strings
* - Logs stdout as info, stderr as error
* - Throws CliError if command fails (non-zero exit code)
*
* @param command - Shell command string to execute
* @returns Promise resolving to stdout and stderr strings
* @throws CliError if command execution fails
*/
execute = async (command) => {
if (this._debug)
this.logDebug(`executing: `, `"""\n${command}\n"""`);
return new Promise((resolve, reject) => {
exec(command, this.cliOptions, (error, stdout, stderr) => {
if (error) {
return reject(new CliError(`executing:\n${command}\n`, toStringWithNewlines(stdout), toStringWithNewlines(stderr), error));
}
if (stdout)
this.logInfo(stdout);
if (stderr)
this.logError(stderr);
resolve({ stdout: toStringWithNewlines(stdout), stderr: toStringWithNewlines(stderr) });
});
});
};
debug(debug) {
this._debug = debug ?? !this._debug;
return this;
}
setShell(shell) {
(this.cliOptions || (this.cliOptions = {})).shell = shell;
}
setOptions(options) {
this.cliOptions = options;
}
setUID(uid) {
this.setTag(uid);
return this;
}
}