@nu-art/commando
Version:
Shell command execution framework with interactive sessions, CLI parameter resolution, and plugin system for building and executing shell scripts programmatically
197 lines (196 loc) • 6.52 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 { BaseCommando } from '../core/BaseCommando.js';
/**
* Basic shell command plugin for Commando.
*
* Provides common file system and shell operations:
* - Directory navigation (`cd`, `pwd`)
* - File operations (`ls`, `cat`, `mkdir`, `rm`, `rmdir`, `cpdir`)
* - Variable assignment
* - Echo with options (escape sequences, file output)
*
* **Usage**: Merge with BaseCommando or other Commando classes to add
* these methods. Typically included via `CommandoPool.allocateCommando()`.
*/
export class Commando_Basic extends BaseCommando {
/**
* Changes directory and optionally executes commands in that directory.
*
* **Behavior**:
* - Changes to the specified directory
* - Increases indentation (for script readability)
* - If `toRun` provided, executes the block and returns to previous directory
* - If `toRun` not provided, caller must call `cd_()` to return
*
* **Note**: Uses `cd -` to return to previous directory (OLDPWD).
*
* @param folderName - Directory path to change to
* @param toRun - Optional command block to execute in the directory
* @returns This instance for method chaining
*/
cd(folderName, toRun) {
this.append(`cd ${folderName}`);
this.indentIn();
if (toRun) {
toRun(this);
this.cd_();
}
return this;
}
/**
* Appends a custom command string.
*
* Allows adding arbitrary shell commands that aren't covered by
* the built-in methods.
*
* @param command - Custom shell command to append
* @returns This instance for method chaining
*/
custom(command) {
this.append(command);
return this;
}
/**
* Changes directory back to the previous directory.
* @returns {this} - The Cli instance for method chaining.
*/
cd_() {
this.indentOut();
this.append(`cd -`);
return this;
}
/**
* Appends an 'ls' command with optional parameters.
* @param {string} [params] - Optional parameters for the 'ls' command.
* @returns {this} - The Cli instance for method chaining.
*/
ls(params = '') {
this.append(`ls ${params}`);
return this;
}
/**
* Creates a directory (with parent directories if needed).
*
* Uses `mkdir -p` to create directory and all parent directories.
*
* @param dirName - Directory path to create
* @returns This instance for method chaining
*/
mkdir(dirName) {
this.append(`mkdir -p ${dirName}`);
return this;
}
/**
* Removes a file or directory.
*
* @param dirPath - Path to remove
* @param options - Optional force flag
* @returns This instance for method chaining
*/
rm(dirPath, options) {
let command = 'rm';
if (options?.force)
command += ' -f';
this.append(`${command} ${dirPath}`);
return this;
}
/**
* Removes a directory recursively.
*
* @param dirPath - Directory path to remove
* @param options - Optional force flag
* @returns This instance for method chaining
*/
rmdir(dirPath, options) {
let command = 'rm -r';
if (options?.force)
command += ' -f';
this.append(`${command} ${dirPath}`);
return this;
}
/**
* Copies a directory.
*
* @param srcPath - Source directory path
* @param destPath - Destination directory path
* @param options - Optional contentOnly flag (copies contents, not directory itself)
* @returns This instance for method chaining
*/
cpdir(srcPath, destPath, options) {
let command = `cp -r ${srcPath}`;
if (options?.contentOnly)
command += '/*';
command += ` ${destPath}`;
this.append(command);
return this;
}
/**
* Displays file contents.
*
* @param fileName - File path to display
* @returns This instance for method chaining
*/
cat(fileName) {
this.append(`cat ${fileName}`);
return this;
}
/**
* Echoes text with optional escape sequences and file output.
*
* **Escape Sequences**: When `escape` is true, enables interpretation
* of backslash escapes (e.g., `\n`, `\t`).
*
* **File Output**: Can append or overwrite to a file.
*
* **Escaping**: Automatically escapes backslashes, newlines, and tabs
* in the log string for safe shell execution.
*
* @param log - Text to echo
* @param options - Optional echo configuration
* @returns This instance for method chaining
*/
echo(log, options) {
const _escape = options?.escape ? '-e' : '';
const _toFile = options?.toFile ? `>${options.toFile.append ? '>' : ''} ${options.toFile.name}` : '';
const escapedLog = log.replace(/\\/g, '\\\\').replace(/\n/g, '\\\\n').replace(/\t/g, '\\\t');
this.append(`echo ${_escape} "${escapedLog}" ${_toFile}`);
return this;
}
/**
* Appends a 'pwd' command to print the current directory.
* @returns {this} - The Cli instance for method chaining.
*/
pwd() {
this.append('pwd');
return this;
}
/**
* Assigns a value to a shell variable (array or scalar).
*
* Creates a bash array if value is an array, otherwise creates a scalar variable.
*
* @param varName - Variable name
* @param value - Value(s) to assign (string or array of strings)
* @returns This instance for method chaining
*/
assignVar(varName, value) {
this.append(`${varName}=(${Array.isArray(value) ? value : [value].join(' ')})`);
return this;
}
}