-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
162 lines (152 loc) · 3.91 KB
/
index.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
var http = require('http');
var codes = Object.keys(http.STATUS_CODES);
/**
* can be called with:
* - ()
* - (err)
* - (message)
* - (code)
* -------
* - (code, message)
* - (code, body)
* - (code, err)
* -------
* - (err, resp, body)
*/
module.exports = function createError(arg1, arg2, arg3) {
var err, code, body;
if (arguments.length <= 1) {
if (typeof arg1 === 'number') {
err = new Error(http.STATUS_CODES[arg1] || '');
code = arg1;
} else if (typeof arg1 === 'string' || arg1 instanceof String) {
var message;
var re = new RegExp(arg1.replace(/_/g, ' '), 'i');
for (var i = 0; i < codes.length; i++) {
if (http.STATUS_CODES[codes[i]].match(re)) {
code = codes[i];
message = http.STATUS_CODES[codes[i]];
break;
}
}
err = new Error(message || arg1);
} else if (arg1 instanceof Error) {
err = arg1;
} else {
err = new Error();
}
}
if (arguments.length === 2) {
code = arg1;
if (
typeof arg2 === 'string' ||
arg2 instanceof String ||
Buffer.isBuffer(arg2)
) {
try {
body = JSON.parse(arg2);
} catch (e) {
err = new Error(arg2);
}
} else if (arg2 instanceof Error) {
err = arg2;
} else if (typeof arg2 === 'object') {
body = arg2;
} else {
err = new Error();
}
}
if (arguments.length === 3) {
if (arg1) {
err = arg1;
}
if (arg2) {
code = arg2.statusCode;
}
if (arg3) {
if (
typeof arg3 == 'string' ||
arg3 instanceof String ||
Buffer.isBuffer(arg3)
) {
try {
arg3 = JSON.parse(arg3);
} catch (e) {}
}
body = arg3;
}
}
// auto handle: create error if code or body are problematic
// !! Couchdb can return 200 or 201 with payload like:
// [{
// "id" : "id1",
// "error" : "conflict",
// "reason" : "Document update conflict."
// }]
if (
!err &&
((code && code >= 400) ||
(body &&
(body['@type'] === 'Error' ||
body.error ||
(Array.isArray(body) &&
body.some(function(obj) {
return (
obj &&
obj.error &&
// science.ai data model can have document with an sa:error property => we make sure to exclude such JSON-LD documents
!obj['@id'] &&
!obj['@type'] &&
!obj['@context']
);
}))))) // Couchb bulk_docs (statusCode will be 200 or 201 or 202 but still some ops may have failed...
) {
// API / hydra error
if (code == null && body.statusCode) {
code = body.statusCode;
}
var message;
var hasConflict;
if (Array.isArray(body)) {
var msgs = [];
body.forEach(function(obj) {
if (obj && typeof obj.error === 'string') {
if (obj.error === 'conflict') {
hasConflict = true;
}
var msg = obj.error;
if (typeof obj.reason === 'string') {
msg += ': ' + obj.reason;
}
if (!~msgs.indexOf(msg)) {
msgs.push(msg);
}
}
});
message = msgs.join('; ');
} else if (typeof body === 'string') {
message = body;
} else if (body) {
if (typeof body.error === 'string' && typeof body.reason === 'string') {
if (body.error === 'conflict') {
hasConflict = true;
}
message = body.error + ': ' + body.reason;
} else {
message = body.error || body.reason || body.description || body.message;
}
}
if (hasConflict && (!code || code < 300)) {
code = 409;
}
err = new Error(typeof message === 'string' ? message : '');
}
if (!err) return null;
if (!('code' in err)) {
err.code = code == null ? 500 : code;
}
if (err.code == 'ENOENT') {
err.code === 404;
}
return err;
};