UNPKG

@ably/cli

Version:

Ably CLI for Pub/Sub, Chat and Spaces

68 lines (67 loc) 2.43 kB
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); } } }