UNPKG

6.03 kBJavaScriptView Raw
1var _ = require('lodash');
2var utils = require('./utils');
3var errors = module.exports;
4
5var canCapture = typeof Error.captureStackTrace === 'function';
6var canStack = !!new Error().stack;
7
8function ErrorAbstract(msg, constructor, metadata) {
9 this.message = msg;
10
11 Error.call(this, this.message);
12
13 if (canCapture) {
14 Error.captureStackTrace(this, constructor);
15 } else if (canStack) {
16 this.stack = new Error().stack;
17 } else {
18 this.stack = '';
19 }
20
21 if (metadata) {
22 _.assign(this, metadata);
23
24 this.toString = function() {
25 return msg + ' :: ' + JSON.stringify(metadata);
26 };
27
28 this.toJSON = function() {
29 return _.assign(
30 {
31 msg: msg,
32 },
33 metadata
34 );
35 };
36 }
37}
38errors._Abstract = ErrorAbstract;
39utils.inherits(ErrorAbstract, Error);
40
41/**
42 * Connection Error
43 * @param {String} [msg] - An error message that will probably end up in a log.
44 */
45errors.ConnectionFault = function ConnectionFault(msg) {
46 ErrorAbstract.call(this, msg || 'Connection Failure', errors.ConnectionFault);
47};
48utils.inherits(errors.ConnectionFault, ErrorAbstract);
49
50/**
51 * No Living Connections
52 * @param {String} [msg] - An error message that will probably end up in a log.
53 */
54errors.NoConnections = function NoConnections(msg) {
55 ErrorAbstract.call(
56 this,
57 msg || 'No Living connections',
58 errors.NoConnections
59 );
60};
61utils.inherits(errors.NoConnections, ErrorAbstract);
62
63/**
64 * Generic Error
65 * @param {String} [msg] - An error message that will probably end up in a log.
66 */
67errors.Generic = function Generic(msg, metadata) {
68 ErrorAbstract.call(this, msg || 'Generic Error', errors.Generic, metadata);
69};
70utils.inherits(errors.Generic, ErrorAbstract);
71
72/**
73 * Request Timeout Error
74 * @param {String} [msg] - An error message that will probably end up in a log.
75 */
76errors.RequestTimeout = function RequestTimeout(msg) {
77 ErrorAbstract.call(this, msg || 'Request Timeout', errors.RequestTimeout);
78};
79utils.inherits(errors.RequestTimeout, ErrorAbstract);
80
81/**
82 * Request Body could not be parsed
83 * @param {String} [msg] - An error message that will probably end up in a log.
84 */
85errors.Serialization = function Serialization(msg) {
86 ErrorAbstract.call(
87 this,
88 msg || 'Unable to parse/serialize body',
89 errors.Serialization
90 );
91};
92utils.inherits(errors.Serialization, ErrorAbstract);
93
94/**
95 * Thrown when a browser compatability issue is detected (cough, IE, cough)
96 */
97errors.RequestTypeError = function RequestTypeError(feature) {
98 ErrorAbstract.call(
99 this,
100 'Cross-domain AJAX requests ' + feature + ' are not supported',
101 errors.RequestTypeError
102 );
103};
104utils.inherits(errors.RequestTypeError, ErrorAbstract);
105
106var statusCodes = [
107 [300, 'Multiple Choices'],
108 [301, 'Moved Permanently'],
109 [302, 'Found'],
110 [303, 'See Other'],
111 [304, 'Not Modified'],
112 [305, 'Use Proxy'],
113 [307, 'Temporary Redirect'],
114 [308, 'Permanent Redirect'],
115 [400, 'Bad Request'],
116 [401, 'Authentication Exception'],
117 [402, 'Payment Required'],
118 [403, ['Authorization Exception', 'Forbidden']],
119 [404, 'Not Found'],
120 [405, 'Method Not Allowed'],
121 [406, 'Not Acceptable'],
122 [407, 'Proxy Authentication Required'],
123 [408, 'Request Timeout'],
124 [409, 'Conflict'],
125 [410, 'Gone'],
126 [411, 'Length Required'],
127 [412, 'Precondition Failed'],
128 [413, 'Request Entity Too Large'],
129 [414, 'Request URIToo Long'],
130 [415, 'Unsupported Media Type'],
131 [416, 'Requested Range Not Satisfiable'],
132 [417, 'Expectation Failed'],
133 [418, 'Im ATeapot'],
134 [421, 'Too Many Connections From This IP'],
135 [426, 'Upgrade Required'],
136 [429, 'Too Many Requests'],
137 [450, 'Blocked By Windows Parental Controls'],
138 [494, 'Request Header Too Large'],
139 [497, 'HTTPTo HTTPS'],
140 [499, 'Client Closed Request'],
141 [500, 'Internal Server Error'],
142 [501, 'Not Implemented'],
143 [502, 'Bad Gateway'],
144 [503, 'Service Unavailable'],
145 [504, 'Gateway Timeout'],
146 [505, 'HTTPVersion Not Supported'],
147 [506, 'Variant Also Negotiates'],
148 [510, 'Not Extended'],
149];
150
151_.each(statusCodes, function createStatusCodeError(tuple) {
152 var status = tuple[0];
153 var names = tuple[1];
154 var allNames = [].concat(names, status);
155 var primaryName = allNames[0];
156 var className = utils.studlyCase(primaryName);
157 allNames = _.uniq(allNames.concat(className));
158
159 function StatusCodeError(msg, metadata) {
160 this.status = status;
161 this.displayName = className;
162
163 var esErrObject = null;
164 if (_.isPlainObject(msg)) {
165 esErrObject = msg;
166 msg = null;
167 }
168
169 if (!esErrObject) {
170 // errors from es now come in two forms, an error string < 2.0 and
171 // an object >= 2.0
172 // TODO: remove after dropping support for < 2.0
173 ErrorAbstract.call(this, msg || primaryName, StatusCodeError, metadata);
174 return this;
175 }
176
177 msg = [].concat(esErrObject.root_cause || []).reduce(function(memo, cause) {
178 if (memo) memo += ' (and) ';
179
180 memo += '[' + cause.type + '] ' + cause.reason;
181
182 var extraData = _.omit(cause, ['type', 'reason']);
183 if (_.size(extraData)) {
184 memo += ', with ' + prettyPrint(extraData);
185 }
186
187 return memo;
188 }, '');
189
190 if (!msg) {
191 if (esErrObject.type) msg += '[' + esErrObject.type + '] ';
192 if (esErrObject.reason) msg += esErrObject.reason;
193 }
194
195 ErrorAbstract.call(this, msg || primaryName, StatusCodeError, metadata);
196 return this;
197 }
198 utils.inherits(StatusCodeError, ErrorAbstract);
199
200 allNames.forEach(function(name) {
201 errors[name] = StatusCodeError;
202 });
203});
204
205function prettyPrint(data) {
206 const path = [];
207 return (function print(v) {
208 if (typeof v === 'object') {
209 if (path.indexOf(v) > -1) return '[circular]';
210 path.push(v);
211 try {
212 return (
213 '{ ' +
214 _.map(v, function(subv, name) {
215 return name + '=' + print(subv);
216 }).join(' & ') +
217 ' }'
218 );
219 } finally {
220 path.pop();
221 }
222 } else {
223 return JSON.stringify(v);
224 }
225 })(data);
226}