Skip to content

Commit

Permalink
Merge pull request #109 from AthennaIO/develop
Browse files Browse the repository at this point in the history
feat(exception): add other infos to errors
  • Loading branch information
jlenon7 authored Jan 15, 2024
2 parents 3b2398e + 2c75acd commit cf741f6
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 7 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@athenna/common",
"version": "4.28.0",
"version": "4.29.0",
"description": "The Athenna common helpers to use in any Node.js ESM project.",
"license": "MIT",
"author": "João Lenon <[email protected]>",
Expand Down
39 changes: 37 additions & 2 deletions src/globals/Error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import * as changeCase from 'change-case'

import { Is } from '#src/helpers/Is'
import { Json } from '#src/helpers/Json'
import type { ExceptionJson } from '#src/types'
import { Exception } from '#src/helpers/Exception'

Expand All @@ -29,8 +31,41 @@ Error.prototype.toAthennaException = function (options: ExceptionJson = {}) {
options.name = options.name || this.name
options.stack = options.stack || this.stack
options.message = options.message || this.message
options.code = options.code || changeCase.constantCase(options.name)
options.details = options.details || this.details || this.errors
options.code =
options.code || this.code || changeCase.constantCase(options.name)
options.otherInfos = {
...options.otherInfos,
...Json.omit(this, [
'name',
'stack',
'message',
'code',
'details',
'errors'
])
}

if (!Is.Undefined(options.details)) {
return new Exception(options)
}

options.details = []

if (!Is.Empty(this.details)) {
if (Is.Array(this.details)) {
options.details.push(...this.details)
} else {
options.details.push(this.details)
}
}

if (!Is.Empty(this.errors)) {
if (Is.Array(this.errors)) {
options.details.push(...this.errors)
} else {
options.details.push(this.errors)
}
}

return new Exception(options)
}
20 changes: 18 additions & 2 deletions src/helpers/Exception.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ import * as changeCase from 'change-case'
import Youch from 'youch'
import YouchTerminal from 'youch-terminal'

import { Is } from '@athenna/common'
import { Color } from '#src/helpers/Color'
import { Options } from '#src/helpers/Options'
import type { ExceptionJson } from '#src/types'
import { Is } from '@athenna/common'

export class Exception extends Error {
public code?: string
public help?: any
public status?: number
public details?: any[]
public otherInfos?: any
public isAthennaException = true

/**
Expand Down Expand Up @@ -52,6 +53,10 @@ export class Exception extends Error {
this.details = options.details
}

if (options.otherInfos) {
this.otherInfos = options.otherInfos
}

if (options.stack) {
this.stack = options.stack
} else {
Expand All @@ -72,6 +77,7 @@ export class Exception extends Error {

if (this.help) json.help = this.help
if (this.details) json.details = this.details
if (this.otherInfos) json.otherInfos = this.otherInfos
if (stack) json.stack = this.stack

return json
Expand Down Expand Up @@ -100,6 +106,7 @@ export class Exception extends Error {
const separator = Color.cyan('-----')
const helpKey = Color.gray.bold.bgGreen(' HELP ')
const detailsKey = Color.gray.bold.bgHex('#f18b0e')(' DETAILS ')
const otherInfosKey = Color.gray.bold.bgHex('#f18b0e')(' OTHER INFOS ')
const title = Color.gray.bold.bgRed(` ${this.code || this.name} `)

let help = ''
Expand All @@ -117,6 +124,14 @@ export class Exception extends Error {
.join('\n')}`
}

if (this.otherInfos && !Is.Empty(this.otherInfos)) {
message = `${message}\n\n${otherInfosKey}\n\n${
Is.String(this.otherInfos)
? Color.orange(Color.apply(this.otherInfos))
: Color.orange(JSON.stringify(this.otherInfos, null, 2))
}`
}

if (this.help && this.help !== '') {
help = `${helpKey}\n\n ${Color.green(
Color.apply(this.help)
Expand All @@ -132,7 +147,8 @@ export class Exception extends Error {
code: this.code,
stack: this.stack,
status: this.status,
details: this.details
details: this.details,
otherInfos: this.otherInfos
}),
{}
).toJSON()
Expand Down
1 change: 1 addition & 0 deletions src/types/json/ExceptionJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export interface ExceptionJson {
message?: string
help?: any
details?: any[]
otherInfos?: any
stack?: string
}
55 changes: 55 additions & 0 deletions tests/unit/ExceptionTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,59 @@ export default class ExceptionTest {
assert.isDefined(prettyError)
assert.typeOf(prettyError, 'string')
}

@Test()
public async shouldBeAbleToPrettifyTheExceptionWithDetailsAndAdditionalErrorInfos({ assert }: Context) {
const error = new Error()

// eslint-disable-next-line
// @ts-ignore
error.code = 'E_RUNTIME_EXCEPTION'
// eslint-disable-next-line
// @ts-ignore
error.line = 0
// eslint-disable-next-line
// @ts-ignore
error.column = 0
// eslint-disable-next-line
// @ts-ignore
error.filename = 'test.js'

const exception = error.toAthennaException()
const prettyError = await exception.prettify()

console.log(prettyError)

assert.isDefined(prettyError)
assert.typeOf(prettyError, 'string')
}

@Test()
public async shouldBeAbleToPrettifyTheExceptionMergingInfosAndAdditionalErrorInfos({ assert }: Context) {
const error = new Error()

// eslint-disable-next-line
// @ts-ignore
error.code = 'E_RUNTIME_EXCEPTION'
// eslint-disable-next-line
// @ts-ignore
error.line = 0
// eslint-disable-next-line
// @ts-ignore
error.column = 0
// eslint-disable-next-line
// @ts-ignore
error.filename = 'test.js'
// eslint-disable-next-line
// @ts-ignore
error.details = ['Machine error']

const exception = error.toAthennaException({ otherInfos: { hello: 'world' } })
const prettyError = await exception.prettify()

console.log(prettyError)

assert.isDefined(prettyError)
assert.typeOf(prettyError, 'string')
}
}

0 comments on commit cf741f6

Please sign in to comment.