@ably/cli
Version:
Ably CLI for Pub/Sub, Chat and Spaces
68 lines (67 loc) • 2.43 kB
JavaScript
import { Command } from "@oclif/core";
import isTestMode from "./utils/test-mode.js";
/**
* Base command class that provides interactive-mode-safe error handling.
* When running in interactive mode, this class converts process.exit calls
* to thrown errors that can be caught and handled gracefully.
*/
export class InteractiveBaseCommand extends Command {
error(input, options) {
const error = typeof input === "string" ? new Error(input) : input;
// In interactive mode, throw the error to be caught
if (process.env.ABLY_INTERACTIVE_MODE === "true" &&
options?.exit !== false) {
// Add oclif error metadata
error.oclif = {
exit: options?.exit ?? 1,
code: options?.code,
};
if (process.env.DEBUG) {
console.error("[InteractiveBaseCommand] Throwing error instead of exiting:", error.message);
}
throw error;
}
// In normal mode or when exit is false, use default behavior
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return super.error(input, options);
}
/**
* Exit is an override of oclif's exit command.
*
* If we're running unit tests, it does nothing, because we don't want to
* quit the test process.
*
* If we're running in interactive mode, we want to throw instead of killing the process.
*
* Otherwise, defer to oclif to kill off the process.
*/
exit(code = 0) {
if (isTestMode()) {
// @ts-expect-error TS2322: suppress type assignment error
return;
}
if (process.env.ABLY_INTERACTIVE_MODE === "true") {
const error = new Error(`Command exited with code ${code}`);
error.exitCode = code;
error.code = "EEXIT";
throw error;
}
super.exit(code);
}
/**
* Override log to ensure proper output in interactive mode
*/
log(message, ...args) {
// If we have this, the command wasn't run in oclif.runCommand, so don't log to avoid polluting.
if (!this.config.root) {
return;
}
// Ensure logs are displayed properly in interactive mode
if (message === undefined) {
console.log();
}
else {
console.log(message, ...args);
}
}
}