-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherror.js
102 lines (81 loc) · 2.43 KB
/
error.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
const NestedError = require('nested-error-stacks')
const _ = require('lodash')
const assert = require('assert')
const { QueryFileError, QueryResultError, queryResultErrorCode } = require('pg-promise').errors
const errors = require('error.toml')
const inProduction = process.env.NODE_ENV === 'production'
// queryResultErrorCode:
// noData: int
// multiple: int
// notEmpty: int
const queryResultErrorName = _.invert(queryResultErrorCode)
function getCode (ec) {
const code = _.get(errors, ec)
console.log(errors, ec, code)
if (!code) throw new TypeError(`invalid error const: ${ec}`)
return code
}
function checkDBErrorMappingKey (key) {
if (!key.includes('_') && !(key in queryResultErrorCode)) {
throw new TypeError(`invalid dbErrorHandler mapping key: ${key}`)
}
}
class GenericError extends NestedError {
constructor (ec, cause, status) {
super(ec, cause)
this.error = ec
this.code = getCode(ec)
this.status = status
}
}
class DatabaseError extends GenericError {}
class HttpError extends GenericError {}
class ValidationError extends GenericError {}
function error (ec, cause, status) {
if (ec.startsWith('db.')) {
return new DatabaseError(ec, cause, status || 500)
}
if (!status) {
const ecParts = ec.split('.')
status = errors.http[_.last(ecParts)]
}
if (ec.startsWith('http.')) {
return new HttpError(ec, cause, status)
}
return new GenericError(ec, cause, status || 400)
}
function dbErrorHandler (mapping = {}) {
if (mapping instanceof DatabaseError) {
throw mapping
}
if (mapping instanceof Error) {
throw error('db.internal', mapping)
}
if (!inProduction) {
_.keys(mapping).forEach(checkDBErrorMappingKey)
_.values(mapping).filter(_.isString).forEach(getCode)
}
return cause => {
if (cause instanceof DatabaseError) {
throw cause
}
const key = cause instanceof QueryResultError
? queryResultErrorName[cause.code]
: cause.constraint
const handle = key && mapping[key]
if (_.isFunction(handle)) {
return handle(cause)
}
throw error(handle || 'db.internal', cause)
}
}
error.db = dbErrorHandler
error.errors = errors
error.AssertionError = assert.AssertionError
error.DatabaseError = DatabaseError
error.GenericError = GenericError
error.HttpError = HttpError
error.QueryFileError = QueryFileError
error.QueryResultError = QueryResultError
error.ValidationError = ValidationError
module.exports = error