UNPKG

2.96 kBJavaScriptView Raw
1/* eslint-disable no-unused-vars, max-classes-per-file */
2const retrieveStatusMeta = (code) =>
3 Object.entries({
4 BadRequest: 400,
5 Authentication: 401,
6 Authorization: 403,
7 ResourceNotFound: 404,
8 Conflict: 409,
9 Gone: 410,
10 Preprocessing: 412,
11 Validation: 422,
12 }).find(([k, v]) => k === code || v === code) || [
13 'InternalServer',
14 500,
15 ];
16
17class Exception {
18 constructor(code) {
19 const [name, statusCode] = retrieveStatusMeta(code);
20 this.code = code;
21 this.name = name;
22 this.statusCode = statusCode;
23 this.errors = {};
24 }
25
26 get $error() {
27 const e = new Error();
28 Object.assign(e, this);
29 return e;
30 }
31
32 field(fieldName) {
33 const formatAPIError = (name, msg, value) => {
34 this.errors[name] = {
35 msg: msg || name,
36 in: 'application',
37 value,
38 };
39 };
40
41 const getFieldNameProps = (name) => {
42 if (typeof fieldName === 'object')
43 return [
44 name || fieldName.name,
45 fieldName.msg,
46 fieldName.value,
47 ];
48
49 return [fieldName];
50 };
51
52 if (
53 typeof fieldName === 'string' ||
54 !Array.isArray(fieldName.name)
55 )
56 formatAPIError(...getFieldNameProps());
57
58 if (Array.isArray(fieldName.name))
59 fieldName.name.forEach((i) => {
60 formatAPIError(...getFieldNameProps(i));
61 });
62
63 return this;
64 }
65
66 msg(msg) {
67 this.message = msg;
68 this.code = msg;
69 return this;
70 }
71
72 boomerang() {
73 return this.$error;
74 }
75
76 log() {
77 // eslint-disable-next-line
78 console.log(this.$error)
79 }
80
81 throw() {
82 throw this.$error;
83 }
84}
85
86const handleUncaughtExceptions = (err, req, res, next) => {
87 // eslint-disable-next-line
88 if (process.env.DEBUG_CONTROLLER) console.log(err);
89
90 const status = err.statusCode || 500;
91 const setHeader = (code) =>
92 !res._headerSent && !res.headersSent
93 ? res.status(code)
94 : undefined;
95
96 const translateMessage = (m) =>
97 req.t ? req.t(`messages:${m}`) : m;
98
99 const translateErrors = (e = {}) =>
100 Object.entries(e).reduce(
101 (a, [key, value]) =>
102 req.t
103 ? Object.assign(a, {
104 [key]: {
105 ...value,
106 msg: req.t(`validations:${value.msg}`),
107 },
108 })
109 : a,
110 {},
111 );
112
113 if (
114 err.errors &&
115 Object.keys(err.errors).length &&
116 status === 500
117 ) {
118 setHeader(422);
119 res.json({
120 message: translateMessage('validation'),
121 errors: translateErrors(err.errors),
122 });
123 } else {
124 setHeader(status);
125 res.json({
126 errors: translateErrors(err.errors),
127 message: translateMessage(err.message),
128 stack: err.stack,
129 name: err.name,
130 });
131 }
132};
133
134module.exports = {
135 exception: (v) => new Exception(v),
136 handleUncaughtExceptions,
137};