diff --git a/packages/@ionic/cli-framework/src/errors.ts b/packages/@ionic/cli-framework/src/errors.ts index 262cc2603..375f3b0b1 100644 --- a/packages/@ionic/cli-framework/src/errors.ts +++ b/packages/@ionic/cli-framework/src/errors.ts @@ -1,3 +1,4 @@ +import * as lodash from 'lodash'; import * as util from 'util'; import { ValidationError } from './definitions'; @@ -9,11 +10,25 @@ export const ERROR_IPC_UNKNOWN_PROCEDURE = 'ERR_ICF_IPC_UNKNOWN_PROCEDURE'; export abstract class BaseError extends Error { abstract readonly name: string; + message: string; + stack: string; code?: string; + error?: Error; exitCode?: number; + constructor(message: string) { + super(message); + this.message = message; + this.stack = (new Error()).stack || ''; + } + toString(): string { - return util.inspect(this); + const repr = lodash.pick(this, lodash.pull(lodash.keys(this), 'error')); + + return ( + `${this.name}: ${this.message} ${util.inspect(repr, { breakLength: Infinity })} ${this.stack} ` + + `${this.error ? `\nWrapped: ${this.error.stack ? this.error.stack : this.error}` : ''}` + ); } inspect(): string { diff --git a/packages/@ionic/cli/src/index.ts b/packages/@ionic/cli/src/index.ts index 9b72945ba..fd9be4481 100644 --- a/packages/@ionic/cli/src/index.ts +++ b/packages/@ionic/cli/src/index.ts @@ -3,7 +3,6 @@ import { readPackageJsonFile } from '@ionic/cli-framework/utils/node'; import { processExit } from '@ionic/utils-process'; import * as Debug from 'debug'; import * as path from 'path'; -import * as util from 'util'; import { IonicNamespace } from './commands'; import { IPCMessage, IonicContext, IonicEnvironment } from './definitions'; @@ -172,7 +171,11 @@ export async function run(pargv: string[]): Promise { } else if (err instanceof BaseError) { ienv.log.error(err.message); } else { - ienv.log.rawmsg(failure(util.inspect(err))); + ienv.log.msg(failure(String(err.stack ? err.stack : err))); + + if (err.stack) { + debug(failure(String(err.stack))); + } } } } diff --git a/packages/@ionic/cli/src/lib/project/index.ts b/packages/@ionic/cli/src/lib/project/index.ts index 77449ca6d..6a1bfa7d6 100644 --- a/packages/@ionic/cli/src/lib/project/index.ts +++ b/packages/@ionic/cli/src/lib/project/index.ts @@ -55,9 +55,9 @@ export class ProjectDetailsError extends BaseException { /** * The underlying error that caused this error. */ - cause?: Error + readonly error?: Error ) { - super(msg, { cause }); + super(msg); } } @@ -193,7 +193,7 @@ export class ProjectDetails { if (e1) { log.error( `Error while loading config (project config: ${strong(prettyPath(result.configPath))})\n` + - `${e1.cause ? `${e1.message}: ${failure(e1.cause.toString())}` : failure(e1.message)}. ` + + `${e1.error ? `${e1.message}: ${failure(e1.error.toString())}` : failure(e1.message)}. ` + `Run ${input('ionic init')} to re-initialize your Ionic project. Without a valid project config, the CLI will not have project context.` ); diff --git a/packages/@ionic/utils-subprocess/src/index.ts b/packages/@ionic/utils-subprocess/src/index.ts index 0ff8bb63b..360762d53 100644 --- a/packages/@ionic/utils-subprocess/src/index.ts +++ b/packages/@ionic/utils-subprocess/src/index.ts @@ -35,11 +35,20 @@ export function convertPATH(path = process.env.PATH || ''): string { export class SubprocessError extends Error { readonly name = 'SubprocessError'; + message: string; + stack: string; code?: typeof ERROR_COMMAND_NOT_FOUND | typeof ERROR_NON_ZERO_EXIT | typeof ERROR_SIGNAL_EXIT; + error?: Error; output?: string; signal?: string; exitCode?: number; + + constructor(message: string) { + super(message); + this.message = message; + this.stack = (new Error()).stack || ''; + } } export interface SubprocessOptions extends SpawnOptions {} @@ -163,12 +172,13 @@ export class Subprocess { let err: SubprocessError; if (error.code === 'ENOENT') { - err = new SubprocessError('Command not found.', { cause: error }); + err = new SubprocessError('Command not found.'); err.code = ERROR_COMMAND_NOT_FOUND; } else { - err = new SubprocessError('Command error.', { cause: error }); + err = new SubprocessError('Command error.'); } + err.error = error; reject(err); }); diff --git a/tsconfig.base.json b/tsconfig.base.json index 282786c62..eb7ce3b6e 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -12,8 +12,7 @@ "target": "ES2021", "types": [], "lib": [ - "ES2021", - "ES2022.Error" + "ES2021" ] } }