app-errors
v0.0.3
Published
Set of reusable errors for apps / apis.
Downloads
8
Readme
app-errors
Set of reusable errors for apps / apis.
Installation
yarn add app-errors
Usage
import {
AppError,
AuthenticationError,
AuhtorizationError,
InternalError,
NotImplementedError,
ValidationError,
wrapError
} from 'app-errors'
// AuthenticationError
try {
parseJwt(token)
} catch (err) {
throw new AuthenticationError({ message: 'Invalid token', err })
}
// AuthorizationError
if (user.role !== 'admin') {
throw new AuthorizationError({ message: 'Only admin can access this resource' })
}
// InternalError
if (somethingGoneWrong) {
throw new InternalError({ message: 'Something gone wrong' })
}
// NotImplementedError
app.post('/new-feature', (req, res, next) => {
next(new NotImplementedError({ message: 'This feature is not implemented yet' }))
})
// ValidationError #1
const err = new ValidationError()
if (!user.email.match(/@gmail\.com$/)) {
err.addDetail({ path: 'email', message: 'Must end with "@gmail.com"' })
}
if (!user.password) {
err.addDetail({ path: 'password', message: 'Password is required' })
}
if (err.hasDetails()) {
throw err
}
// ValidationError #2
const errors = [
{ path: 'email', message: 'Must end with "@gmail.com"' },
{ path: 'password', message: 'Password is required' }
]
if (errors.length) {
throw new ValidationError({ details: errors })
}
// wrapError
try {
someCode()
} catch (err) {
err = wrapError(err)
console.log(err instanceof AppError) // true
}
Options
All errors extend AppError
.AppError
(as well as other error classes) accepts following options in constructor:
| option | description |------------|----------- | message | Error message. Defaults to message specific to error class (see table below). | err | Original error. | type | Type of error. Defaults to type specific to error class (see table below). | severity | Severity of error. Defaults to severity specific to error class (see table below). | statusCode | HTTP status code. Defaults status code specific to error class (see table below). | data | Custom error data. Defaults to null. | details | Error details. Defaults to null
Default option values for each error class:
| | message | err | type | severity | statusCode | data | details |---------------------|----------------------|------|----------------|----------|------------|------|-------- | AppError | App error | null | internal | error | 500 | null | null | AuthenticationError | Authentication error | null | authentication | warning | 401 | null | null | AuhtorizationError | Authorization error | null | authorization | warning | 403 | null | null | InternalError | Internal error | null | internal | error | 500 | null | null | NotImplementedError | NotImplemented error | null | internal | error | 503 | null | null | ValidationError | Validation error | null | validation | warning | 400 | null | null
Methods
AppError#getOriginalError()
Return original error.
AppError#getType()
Return error type.
AppError#getSeverity()
Return error severity.
AppError#getStatusCode()
Return error HTTP status code.
AppError#getData()
Return error custom data.
AppError#getDetails()
Return error details.
AppError#addDetail({ path: String, message: String })
Add error detail.
AppError#addDetails(Array<{ path: String, message: String }>)
Add many error details at once.
AppError#hasDetails()
Return true if error has at least one detail.
AppError#toJSON()
Get JSON representation of error. Example:
console.log(new AuthenticationError('hello').toJSON())
/*
{
type: 'authentication',
severity: 'warning',
message: 'hello',
details: [{ path: 'email', message: 'Invalid email' }] // defaults to null if no details were added
}
*/
Note that err.data
is not returned in JSON representation of error.
wrapError(err: Error) => err: AppError
wrapError
converts error to AppError
.
If err passed as argument is already instance of AppError
then it returns passed err.
If err passed as argument is not instance of AppError
it is wrapped in InternalError
.
Example:
const originalErr = new Error('test')
const err = wrapError(originalErr)
console.log(err instanceof AppError) // true
console.log(err instanceof InternalError) // true
console.log(err.message) // 'Internal error'
console.log(err.getOriginalError() instanceof originalErr) // true
This method is useful when globally handling application errors:
app.use(async (ctx, next) => {
try {
await next()
} catch (err) {
err = wrapError(err)
logError(err)
ctx.status = err.getStatusCode()
ctx.body = err.toJSON() // remember that ValidationError#toJSON may return array!
}
})
function logError (err) {
if (err.getSeverity() === 'error') {
console.error(err.getOriginalError().stack)
}
}