From bc33e63e3e7556974b124f63378906e5f5e80e15 Mon Sep 17 00:00:00 2001 From: Joakim Carlstein Date: Tue, 12 Dec 2023 15:36:30 +0100 Subject: [PATCH] feat(reporter-default): improve error logging by logging all own properties of the errors --- .changeset/soft-days-marry.md | 5 ++++ packages/cli/src/errors.ts | 1 - packages/cli/src/reporters/default.ts | 33 ++++++++++++++++++++------- 3 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 .changeset/soft-days-marry.md diff --git a/.changeset/soft-days-marry.md b/.changeset/soft-days-marry.md new file mode 100644 index 0000000..a2844b8 --- /dev/null +++ b/.changeset/soft-days-marry.md @@ -0,0 +1,5 @@ +--- +'@emigrate/cli': minor +--- + +Improve error logging in the default reporter so that all "own properties" of errors are logged diff --git a/packages/cli/src/errors.ts b/packages/cli/src/errors.ts index 63cf19b..d728336 100644 --- a/packages/cli/src/errors.ts +++ b/packages/cli/src/errors.ts @@ -11,7 +11,6 @@ export class EmigrateError extends Error { options?: ErrorOptions, ) { super(message, options); - this.name = `${this.name} [${this.code}]`; } } diff --git a/packages/cli/src/reporters/default.ts b/packages/cli/src/reporters/default.ts index 7cf3f5c..b18fb58 100644 --- a/packages/cli/src/reporters/default.ts +++ b/packages/cli/src/reporters/default.ts @@ -12,6 +12,7 @@ import { type ReporterInitParameters, type Awaitable, } from '@emigrate/plugin-tools/types'; +import { EmigrateError } from '../errors.js'; type Status = ReturnType; @@ -128,19 +129,35 @@ const getError = (error?: ErrorLike, indent = ' ') => { return ''; } - let errorTitle: string; let stack: string[] = []; if (error.stack) { - // @ts-expect-error error won't be undefined here - [errorTitle, ...stack] = error.stack.split('\n'); - } else if (error.name) { - errorTitle = `${error.name}: ${error.message}`; - } else { - errorTitle = error.message; + const stackParts = error.stack.split('\n'); + const messageParts = (error.message ?? '').split('\n'); + + stack = stackParts.slice(messageParts.length); } - const parts = [`${indent}${bold.red(errorTitle)}`, ...stack.map((line) => `${indent}${dim(line)}`)]; + const properties = Object.getOwnPropertyNames(error).filter( + (property) => !['name', 'message', 'stack', 'cause'].includes(property), + ); + const others: Record = {}; + + for (const property of properties) { + others[property] = error[property as keyof ErrorLike]; + } + + const codeString = typeof others['code'] === 'string' ? others['code'] : undefined; + const code = codeString ? ` [${codeString}]` : ''; + + const errorTitle = error.name + ? `${error.name}${codeString && !error.name.includes(codeString) ? code : ''}: ${error.message}` + : error.message; + const parts = [`${indent}${bold.red(errorTitle)}`, ...stack.map((line) => `${indent} ${dim(line.trim())}`)]; + + if (properties.length > 0 && !(error instanceof EmigrateError)) { + parts.push(`${indent} ${JSON.stringify(others, undefined, 2).split('\n').join(`\n${indent} `)}`); + } if (isErrorLike(error.cause)) { const nextIndent = `${indent} `;