@nu-art/commando
Version:
181 lines (180 loc) • 6.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommandoInteractive = void 0;
const ts_common_1 = require("@nu-art/ts-common");
const InteractiveShell_1 = require("./InteractiveShell");
const BaseCommando_1 = require("../core/BaseCommando");
class CommandoInteractive extends BaseCommando_1.BaseCommando {
/**
* Creates a new instance of CommandoInteractive merged with the provided plugins.
* @param {Constructor<any>[]} plugins - The plugins to merge with CommandoInteractive.
* @returns {CommandoInteractive} - The new instance of CommandoInteractive merged with the plugins.
*/
static create(...plugins) {
const _commando = BaseCommando_1.BaseCommando._create(CommandoInteractive, ...plugins);
const commando = _commando;
commando.shell = new InteractiveShell_1.InteractiveShell();
commando.shell.setMinLevel(ts_common_1.LogLevel.Verbose);
return commando;
}
/**
* Constructs a CommandoInteractive instance.
*/
constructor() {
super();
this.shell = new InteractiveShell_1.InteractiveShell();
}
/**
* Toggles or sets the debug mode.
* @param {boolean} [debug] - If provided, sets the debug mode to this value. Otherwise, toggles the current debug mode.
* @returns {boolean} - The current state of debug mode.
*/
debug(debug) {
this.shell.debug(debug);
return super.debug(debug);
}
/**
* Sets the UID for the shell.
* @param {string} uid - The UID to set.
* @returns {this} - The CommandoInteractive instance for method chaining.
*/
setUID(uid) {
this.shell.setUID(uid);
return this;
}
/**
* Closes the shell, optionally with a callback function.
* @returns {this} - The CommandoInteractive instance for method chaining.
*/
close() {
return this.shell.endInteractive();
}
/**
* Kills the shell process with a given signal.
* @param {NodeJS.Signals | number} [signal] - The signal to send to the process.
* @returns {boolean} - Whether the kill signal was successfully sent.
*/
kill(signal) {
return this.shell.kill(signal);
}
/**
* Gracefully kills a process by its PID.
* @param {number} [pid] - The PID of the process to kill.
*/
async gracefullyKill(pid) {
return this.shell.gracefullyKill(pid);
}
/**
* Waits for a log entry that matches a specified pattern, then executes a callback.
* @param {string | RegExp} filter - The pattern to match in log entries.
* @param {(match: RegExpMatchArray) => any} callback - The callback to execute when a match is found.
*/
onLog(filter, callback) {
const regexp = typeof filter === 'string' ? new RegExp(filter) : filter;
const logFilter = (log) => {
const match = log.match(regexp);
if (!match)
return true;
callback(match);
return true;
};
this.addLogProcessor(logFilter);
return this;
}
/**
* Executes commands asynchronously and listens for the PID.
*
* @param {Function} pidListener - A listener function to handle the PID.
* @param {Function} [callback] - A callback function to handle the command output.
* @returns {Promise<T>} - The result of the callback function.
*/
async executeAsync(pidListener, callback) {
const pidUniqueKey = (0, ts_common_1.generateHex)(16);
const regexp = new RegExp(`${pidUniqueKey}=(\\d+)`);
const functionContent = this.builder.reset().trim() + ' &';
const pidLogProcessor = (log) => {
const match = log.match(regexp);
if (!match)
return true;
const pid = +match[1];
pidListener(pid);
return false;
};
return await this
.append(functionContent)
.append('pid=$!')
.append(`echo "${pidUniqueKey}=\${pid}"`)
.append(`wait \$pid`)
.addLogProcessor(pidLogProcessor)
.execute(callback);
}
/**
* Executes commands and processes logs to extract exit code.
* @param {Function} [callback] - A callback function to handle the command output.
* @returns {Promise<T>} - The result of the callback function.
*/
async execute(callback) {
return await new Promise((resolve, reject) => {
const uniqueKey = (0, ts_common_1.generateHex)(16);
const regexp = new RegExp(`${uniqueKey}=(\\d+)`);
let _stderr = '';
let _stdout = '';
const logProcessor = (log, type) => {
if (type === 'err')
_stderr += `${log}\n`;
else
_stdout += `${log}\n`;
if (!log.includes(uniqueKey))
return true;
const match = log.match(regexp);
if (!match)
return true;
const exitCode = match === null || match === void 0 ? void 0 : match[1];
this.removeLogProcessor(logProcessor);
try {
resolve(callback === null || callback === void 0 ? void 0 : callback(_stdout, _stderr, +exitCode));
}
catch (err) {
reject(err);
}
return false;
};
this.builder.append(`echo ${uniqueKey}=$?`);
const command = this.builder.reset();
this.shell.addLogProcessor(logProcessor);
this.shell.execute(command);
});
}
/**
* Adds a log processor to the shell.
* @param {Function} processor - The log processor function to add.
* @returns {this} - The CommandoInteractive instance for method chaining.
*/
addLogProcessor(processor) {
this.shell.addLogProcessor(processor);
return this;
}
setLogLevelFilter(processor) {
this.shell.setLogLevelFilter(processor);
return this;
}
/**
* Removes a log processor from the shell.
* @param {Function} processor - The log processor function to remove.
* @returns {this} - The CommandoInteractive instance for method chaining.
*/
removeLogProcessor(processor) {
this.shell.removeLogProcessor(processor);
return this;
}
/**
* Appends a command to the command list.
* @param {string} command - The command to append.
* @returns {this} - The CommandoInteractive instance for method chaining.
*/
append(command) {
this.builder.append(command);
return this;
}
}
exports.CommandoInteractive = CommandoInteractive;