├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── common.js
├── index.js
├── lib
├── alreadyInUse.js
├── argument.js
├── argumentNull.js
├── authenticationRequired.js
├── data
│ ├── data.js
│ └── status-codes.js
├── helpers
│ └── class-generator.js
├── http-status.js
├── internal
│ └── globalize.js
├── invalid-operation.js
├── io
│ ├── file-load.js
│ ├── file-not-found.js
│ └── io.js
├── middleware
│ ├── crashProtector.js
│ └── errorHandler.js
├── not-found.js
├── not-supported.js
├── notPermitted.js
├── timeout.js
└── validation.js
├── package.json
└── tests
├── already-in-use.js
├── argument-null.js
├── argument.js
├── authentication-required.js
├── connection.js
├── data
├── data.js
├── memcached.js
├── mongodb.js
├── redis.js
├── rollback.js
├── sql.js
└── transaction.js
├── error.js
├── helpers
├── class-generator.js
└── util.js
├── http-status.js
├── invalid-operation.js
├── io
├── directory-not-found.js
├── drive-not-found.js
├── end-of-stream.js
├── file-load.js
├── file-not-found.js
├── io.js
└── socket.js
├── log.js
├── middleware
└── errorHandler.js
├── not-found.js
├── not-implemented.js
├── not-permitted.js
├── not-supported.js
├── out-of-memory.js
├── range.js
├── reference.js
├── stack-overflow.js
├── support
└── index.js
├── syntax.js
├── timeout.js
├── type.js
├── uri.js
└── validation.js
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 |
10 | pids
11 | logs
12 | results
13 |
14 | node_modules
15 | npm-debug.log
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4.1"
4 | - "6.10"
5 | - "8.0"
6 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at open-source@shutterstock.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute
2 |
3 | Please contribute! Here are some things that would be great:
4 | - [Open an issue!](https://github.com/shutterstock/node-common-errors/issues/new)
5 | - Open a pull request!
6 | - Say hi! :wave:
7 |
8 | Please abide by the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
9 |
10 | For more on contributing at [@shutterstock](https://github.com/shutterstock), check out [our welcome repository](https://github.com/shutterstock/welcome).
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013-2017 Shutterstock Images, LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | common-errors
2 | ===========
3 |
4 | > Common error classes and utility functions
5 |
6 | * Full suite of node.js Error classes like most other modern languages
7 | * Append stack traces from other asynchronously generated Errors
8 | * Generate your own custom Error classes in one line
9 | * Map HTTP status codes to Errors for automatic handling in web services and applications
10 |
11 | [](http://travis-ci.org/shutterstock/node-common-errors)
12 |
13 | ## Install
14 | ```npm install common-errors```
15 |
16 | ## Class Directory
17 |
18 | ### Common Error Classes
19 |
20 | * [AlreadyInUseError](#alreadyinuse)
21 | * [ArgumentError](#argument)
22 | * [ArgumentNullError](#argumentnull)
23 | * [AuthenticationRequiredError](#authrequired)
24 | * [ConnectionError](#connection)
25 | * [DataError](#data)
26 | * [MemcacedError](#memcached)
27 | * [MongoDBError](#mongodb)
28 | * [RedisError](#redis)
29 | * [RollbackError](#rollback)
30 | * [SQLError](#sql)
31 | * [TransactionError](#transaction)
32 | * [Error](#error)
33 | * [HttpStatusError](#httpstatus)
34 | * [InvalidOperationError](#invalidoperation)
35 | * [IOError](#io)
36 | * [DirectoryNotFoundError](#directorynotfound)
37 | * [DriveNotFoundError](#drivenotfound)
38 | * [EndOfStreamError](#endofstream)
39 | * [FileLoadError](#fileload)
40 | * [FileNotFoundError](#filenotfound)
41 | * [SocketError](#socket)
42 | * [NotFoundError](#notfound)
43 | * [NotImplementedError](#notimplemented)
44 | * [NotPermittedError](#notpermitted)
45 | * [NotSupportedError](#notsupported)
46 | * [OutOfMemoryError](#outofmemory)
47 | * [RangeError](#range)
48 | * [ReferenceError](#reference)
49 | * [StackOverflowError](#stackoverflow)
50 | * [SyntaxError](#syntax)
51 | * [TimeoutError](#timeout)
52 | * [TypeError](#type)
53 | * [URIError](#uri)
54 | * [ValidationError](#validation)
55 |
56 |
57 | ### Utility Functions
58 |
59 | * [log](#log)
60 | * [prependCurrentStack](#prependCurrentStack)
61 | * [generateClass](#generateClass)
62 |
63 | ### Express Middleware Functions
64 |
65 | * [Crash Protector](#crashprotector)
66 | * [Error Handler](#errorhandler)
67 |
68 | ## Common Error Classes
69 |
70 |
71 |
72 | ### AlreadyInUseError
73 |
74 | Applicable when a resource is already in use, for example unique key constraints like a username.
75 |
76 | new AlreadyInUseError(entityName, arg1, [arg2, arg3, arg4, ...])
77 |
78 | __Arguments__
79 |
80 | * `entityName` - the entity that owns the protected resource
81 | * `args` - the fields or attributes that are already in use
82 |
83 | ```js
84 | // Example
85 | throw new errors.AlreadyInUseError('user', 'username');
86 | ```
87 |
88 | ---------------------------------------
89 |
90 |
91 |
92 | ### ArgumentError
93 |
94 | Applicable when there's a generic problem with an argument received by a function call.
95 |
96 | new ArgumentError(argumentName[, inner_error])
97 |
98 | __Arguments__
99 |
100 | * `argumentName` - the name of the argument that has a problem
101 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
102 |
103 | ```js
104 | // Example
105 | throw new errors.ArgumentError('username', err);
106 | ```
107 |
108 | ---------------------------------------
109 |
110 |
111 |
112 | ### ArgumentNullError
113 |
114 | Applicable when an argument received by a function call is null/undefined or empty.
115 |
116 | new ArgumentNullError(argumentName[, inner_error])
117 |
118 | __Arguments__
119 |
120 | * `argumentName` - the name of the argument that is null
121 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
122 |
123 | ```js
124 | // Example
125 | throw new errors.ArgumentNullError('username', err);
126 | ```
127 |
128 | ---------------------------------------
129 |
130 |
131 |
132 | ### AuthenticationRequiredError
133 |
134 | Applicable when an operation requires authentication
135 |
136 | new AuthenticationRequiredError(message, [inner_error])
137 |
138 | __Arguments__
139 |
140 | * `message` - any message
141 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
142 |
143 | ```js
144 | // Example
145 | throw new errors.AuthenticationRequiredError("Please provide authentication.", err)
146 | ```
147 |
148 | ---------------------------------------
149 |
150 |
151 |
152 | ### ConnectionError
153 |
154 | Applicable when an error occurs on a connection.
155 |
156 | new ConnectionError(message[, inner_error])
157 |
158 | __Arguments__
159 |
160 | * `message` - any message
161 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
162 |
163 | ```js
164 | // Example
165 | throw new errors.ConnectionError('database connection no longer available', err);
166 | ```
167 |
168 | ---------------------------------------
169 |
170 |
171 |
172 | ### DataError
173 |
174 | Applicable when an error occurs on or with an external data source.
175 |
176 | new DataError(message[, inner_error])
177 |
178 | __Arguments__
179 |
180 | * `message` - any message
181 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
182 |
183 | ```js
184 | // Example
185 | throw new errors.data.DataError('Too many rows returned from database', err);
186 | ```
187 |
188 | ---------------------------------------
189 |
190 |
191 |
192 | ### MemcachedError
193 |
194 | Applicable when an error occurs while using memcached.
195 |
196 | new MemcachedError(message[, inner_error])
197 |
198 | __Arguments__
199 |
200 | * `message` - any message
201 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
202 |
203 | ```js
204 | // Example
205 | throw new errors.data.MemcachedError('Expected value not found', err);
206 | ```
207 |
208 | ---------------------------------------
209 |
210 |
211 |
212 | ### MongoDBError
213 |
214 | Applicable when an error occurs while using MongoDB.
215 |
216 | new MongoDBError(message[, inner_error])
217 |
218 | __Arguments__
219 |
220 | * `message` - any message
221 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
222 |
223 | ```js
224 | // Example
225 | throw new errors.data.MongoDBError('Retrieved value not in expected format', err);
226 | ```
227 |
228 | ---------------------------------------
229 |
230 |
231 |
232 | ### RedisError
233 |
234 | Applicable when an error occurs while using redis.
235 |
236 | new RedisError(message[, inner_error])
237 |
238 | __Arguments__
239 |
240 | * `message` - any message
241 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
242 |
243 | ```js
244 | // Example
245 | throw new errors.data.RedisError('expected value not found in redis', err);
246 | ```
247 |
248 | ---------------------------------------
249 |
250 |
251 |
252 | ### RollbackError
253 |
254 | Applicable when a transaction was unexpectedly rolled back.
255 |
256 | new RollbackError(message[, inner_error])
257 |
258 | __Arguments__
259 |
260 | * `message` - any message
261 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
262 |
263 | ```js
264 | // Example
265 | throw new errors.data.RollbackError('database transaction was unexpectedly rolled back', err);
266 | ```
267 |
268 | ---------------------------------------
269 |
270 |
271 |
272 | ### SQLError
273 |
274 | Applicable when an error occurs while using a SQL database.
275 |
276 | new SQLError(message[, inner_error])
277 |
278 | __Arguments__
279 |
280 | * `message` - any message
281 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
282 |
283 | ```js
284 | // Example
285 | throw new errors.data.SQLError('foreign key constraint violated', err);
286 | ```
287 |
288 | ---------------------------------------
289 |
290 |
291 |
292 | ### TransactionError
293 |
294 | Applicable when an error unexpectedly interrupts a transaction.
295 |
296 | new TransactionError(message[, inner_error])
297 |
298 | __Arguments__
299 |
300 | * `message` - any message
301 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
302 |
303 | ```js
304 | // Example
305 | throw new errors.data.TransactionError('transaction already complete', err);
306 | ```
307 |
308 | ---------------------------------------
309 |
310 |
311 |
312 | ### Error
313 |
314 | This is roughly the same as the native Error class. It additionally supports an inner_error attribute.
315 |
316 | new Error(message, [inner_error])
317 |
318 | __Arguments__
319 |
320 | * `message` - any message
321 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
322 |
323 | ```js
324 | // Example
325 | throw new errors.Error("Please provide authentication.", err)
326 | ```
327 |
328 | ---------------------------------------
329 |
330 |
331 |
332 | ### HttpStatusError
333 |
334 | Represents a message and a HTTP status code.
335 |
336 | new HttpStatusError(status_code[, message])
337 |
338 | __Arguments__
339 |
340 | * `status_code` - any HTTP status code integer
341 | * `message` - any message
342 |
343 | ```js
344 | // Example
345 | throw new errors.HttpStatusError(404, "Not Found");
346 | ```
347 |
348 | new HttpStatusError(err[, req])
349 |
350 | Figure out a proper status code and message from a given error. The current mapping of error codes
351 | to HTTP status codes is as follows:
352 |
353 | ```javascript
354 | {
355 | "ValidationError": 400,
356 | "ArgumentError": 400,
357 | "AuthenticationRequiredError": 401,
358 | "NotPermittedError": 403,
359 | "ArgumentNullError": 404 // , or 400 depending on what's wrong with the request
360 | "NotFoundError": 404,
361 | "NotSupportedError": 405,
362 | "AlreadyInUseError": 409,
363 | }
364 | ```
365 |
366 | To change the mappings, modify `HttpStatusError.message_map` and `HttpStatusError.code_map`
367 |
368 | __Arguments__
369 |
370 | * `err` - any instanceof Error
371 | * `req` - the request object
372 |
373 |
374 |
375 | ```js
376 | // Example
377 | throw new errors.HttpStatusError(err, req);
378 | ```
379 |
380 | ---------------------------------------
381 |
382 |
383 |
384 | ### InvalidOperationError
385 |
386 | Applicable when an invalid operation occurs.
387 |
388 | new InvalidOperationError(message[, inner_error])
389 |
390 | __Arguments__
391 |
392 | * `message` - any message
393 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
394 |
395 | ```js
396 | // Example
397 | throw new errors.InvalidOperationError('divide by zero', err);
398 | ```
399 |
400 | ---------------------------------------
401 |
402 |
403 |
404 | ### IOError
405 |
406 | Base class for Errors while accessing information using streams, files and directories.
407 |
408 | new IOError(message[, inner_error])
409 |
410 | __Arguments__
411 |
412 | * `message` - any message
413 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
414 |
415 | ```js
416 | // Example
417 | throw new errors.io.IOError("Could not open file", err)
418 | ```
419 |
420 | ---------------------------------------
421 |
422 |
423 |
424 | ### DirectoryNotFoundError
425 |
426 | Applicable when part of a file or directory cannot be found.
427 |
428 | new DirectoryNotFoundError(message[, inner_error])
429 |
430 | __Arguments__
431 |
432 | * `message` - any message
433 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
434 |
435 | ```js
436 | // Example
437 | throw new errors.io.DirectoryNotFoundError("/var/log", err)
438 | ```
439 |
440 | ---------------------------------------
441 |
442 |
443 |
444 | ### DriveNotFoundError
445 |
446 | Applicable when trying to access a drive or share that is not available.
447 |
448 | new DriveNotFoundError(message[, inner_error])
449 |
450 | __Arguments__
451 |
452 | * `message` - any message
453 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
454 |
455 | ```js
456 | // Example
457 | throw new errors.io.DriveNotFoundError("c", err)
458 | ```
459 |
460 | ---------------------------------------
461 |
462 |
463 |
464 | ### EndOfStreamError
465 |
466 | Applicable when reading is attempted past the end of a stream.
467 |
468 | new EndOfStreamError(message[, inner_error])
469 |
470 | __Arguments__
471 |
472 | * `message` - any message
473 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
474 |
475 | ```js
476 | // Example
477 | throw new errors.io.EndOfStreamError("EOS while reading header", err)
478 | ```
479 |
480 | ---------------------------------------
481 |
482 |
483 |
484 | ### FileLoadError
485 |
486 | Applicable when a file is found and read but cannot be loaded.
487 |
488 | new FileLoadError(message[, inner_error])
489 |
490 | __Arguments__
491 |
492 | * `file_name` - any message
493 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
494 |
495 | ```js
496 | // Example
497 | throw new errors.io.FileLoadError("./package.json", err)
498 | ```
499 |
500 | ---------------------------------------
501 |
502 |
503 |
504 | ### FileNotFoundError
505 |
506 | Applicable when an attempt to access a file that does not exist on disk fails.
507 |
508 | new FileNotFoundError(message[, inner_error])
509 |
510 | __Arguments__
511 |
512 | * `file_name` - any message
513 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
514 |
515 | ```js
516 | // Example
517 | throw new errors.io.FileNotFoundError("./package.json", err)
518 | ```
519 |
520 | ---------------------------------------
521 |
522 |
523 |
524 | ### SocketError
525 |
526 | Applicable when an error occurs on a socket.
527 |
528 | new SocketError(message[, inner_error])
529 |
530 | __Arguments__
531 |
532 | * `message` - any message
533 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
534 |
535 | ```js
536 | // Example
537 | throw new errors.SocketError('socket no longer available', err);
538 | ```
539 |
540 | ---------------------------------------
541 |
542 |
543 |
544 | ### NotFoundError
545 |
546 | Applicable when an attempt to retrieve data yielded no result.
547 |
548 | new NotFoundError(entity_name[, inner_error])
549 |
550 | __Arguments__
551 |
552 | * `entity_name` - a description for what was not found
553 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
554 |
555 | ```js
556 | // Example
557 | throw new errors.NotFoundError("User", err)
558 | ```
559 |
560 | ---------------------------------------
561 |
562 |
563 |
564 | ### NotImplementedError
565 |
566 | Applicable when a requested method or operation is not implemented.
567 |
568 | new NotImplementedError(message[, inner_error])
569 |
570 | __Arguments__
571 |
572 | * `message` - any message
573 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
574 |
575 | ```js
576 | // Example
577 | throw new errors.NotImplementedError("Method is not yet implemented.", err)
578 | ```
579 |
580 | ---------------------------------------
581 |
582 |
583 |
584 | ### NotPermittedError
585 |
586 | Applicable when an operation is not permitted
587 |
588 | new NotPermittedError(message[, inner_error])
589 |
590 | __Arguments__
591 |
592 | * `message` - any message
593 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
594 |
595 | ```js
596 | // Example
597 | throw new errors.NotPermittedError("username cannot be changed once set.", err)
598 | ```
599 |
600 | ---------------------------------------
601 |
602 |
603 |
604 | ### NotSupportedError
605 |
606 | Applicable when a certain condition is not supported by your application.
607 |
608 | new NotSupportedError(message[, inner_error])
609 |
610 | __Arguments__
611 |
612 | * `message` - a message
613 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
614 |
615 | ```js
616 | // Example
617 | throw new errors.NotSupportedError('Zero values', err);
618 | ```
619 |
620 | ---------------------------------------
621 |
622 |
623 |
624 | ### OutOfMemoryError
625 |
626 | Applicable when there is not enough memory to continue the execution of a program.
627 |
628 | new OutOfMemoryError(message[, inner_error])
629 |
630 | __Arguments__
631 |
632 | * `message` - a message
633 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
634 |
635 | ```js
636 | // Example
637 | throw new errors.OutOfMemoryError('Maximum mem size exceeded.', err);
638 | ```
639 |
640 | ---------------------------------------
641 |
642 |
643 |
644 | ### RangeError
645 |
646 | Represents an error that occurs when a numeric variable or parameter is outside of its valid range. This is roughly the same as the native RangeError class. It additionally supports an inner_error attribute.
647 |
648 | new RangeError(message[, inner_error])
649 |
650 | __Arguments__
651 |
652 | * `message` - a message
653 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
654 |
655 | ```js
656 | // Example
657 | throw new errors.RangeError("Value must be between " + MIN + " and " + MAX, err);
658 | ```
659 |
660 | ---------------------------------------
661 |
662 |
663 |
664 | ### ReferenceError
665 |
666 | Represents an error when a non-existent variable is referenced. This is roughly the same as the native ReferenceError class. It additionally supports an inner_error attribute.
667 |
668 | new ReferenceError(message[, inner_error])
669 |
670 | __Arguments__
671 |
672 | * `message` - a message
673 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
674 |
675 | ```js
676 | // Example
677 | throw new errors.ReferenceError("x is not defined", err);
678 | ```
679 |
680 | ---------------------------------------
681 |
682 |
683 |
684 | ### StackOverflowError
685 |
686 | Applicable when the execution stack overflows because it contains too many nested method calls.
687 |
688 | new StackOverflowError(message[, inner_error])
689 |
690 | __Arguments__
691 |
692 | * `message` - a message
693 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
694 |
695 | ```js
696 | // Example
697 | throw new errors.StackOverflowError('Stack overflow detected.', err);
698 | ```
699 |
700 | ---------------------------------------
701 |
702 |
703 |
704 | ### SyntaxError
705 |
706 | Represents an error when trying to interpret syntactically invalid code. This is roughly the same as the native SyntaxError class. It additionally supports an inner_error attribute.
707 |
708 | new SyntaxError(message[, inner_error])
709 |
710 | __Arguments__
711 |
712 | * `message` - a message
713 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
714 |
715 | ```js
716 | // Example
717 | throw new errors.SyntaxError("Unexpected token a", err);
718 | ```
719 |
720 | ---------------------------------------
721 |
722 |
723 |
724 | ### TimeoutError
725 |
726 | Applicable when an operation takes longer than the alloted amount.
727 |
728 | new TimeoutError(time[, inner_error])
729 |
730 | __Arguments__
731 |
732 | * `time` - a time duration
733 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
734 |
735 | ```js
736 | // Example
737 | throw new errors.TimeoutError('100ms', err);
738 | ```
739 |
740 | ---------------------------------------
741 |
742 |
743 |
744 | ### TypeError
745 |
746 | Represents an error when a value is not of the expected type. This is roughly the same as the native TypeError class. It additionally supports an inner_error attribute.
747 |
748 | new TypeError(message[, inner_error])
749 |
750 | __Arguments__
751 |
752 | * `message` - a message
753 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
754 |
755 | ```js
756 | // Example
757 | throw new errors.TypeError("number is not a function", err);
758 | ```
759 |
760 | ---------------------------------------
761 |
762 |
763 |
764 | ### URIError
765 |
766 | Represents an error when a value is not of the expected type. This is roughly the same as the native URIError class. It additionally supports an inner_error attribute.
767 |
768 | new URIError(message[, inner_error])
769 |
770 | __Arguments__
771 |
772 | * `message` - a message
773 | * `inner_error` - the Error instance that caused the current error. Stack trace will be appended.
774 |
775 | ```js
776 | // Example
777 | throw new errors.URIError("URI malformed", err);
778 | ```
779 |
780 | ---------------------------------------
781 |
782 |
783 |
784 | ### ValidationError
785 |
786 | Useful for denoting a problem with a user-defined value. Generally, you won't throw this error.
787 | It serializes to JSON, and it can also function as an envelope for multiple errors.
788 |
789 | new ValidationError(message, [code], [field])
790 |
791 | __Arguments__
792 |
793 | * `message` - any message
794 | * `code` - an optional error code
795 | * `field` - an optional description of the data
796 |
797 | __Methods__
798 |
799 | * `addError(error)` - add an error object to the `errors` array, and return `this`.
800 | * `addErrors(errors)` - append an array of error objects to the `errors` array, and return `this`.
801 |
802 | ```js
803 | // Example
804 | function validateUsername(username){
805 | var errors = new errors.ValidationError();
806 | if(username.length < 3) errors.addError(new errors.ValidationError("username must be at least two characters long", "VAL_MIN_USERNAME_LENGTH", "username"));
807 | if(/-%$*&!/.test(username)) errors.addError(new errors.ValidationError("username may not contain special characters", "VAL_USERNAME_SPECIALCHARS", "username"));
808 | return errors;
809 | }
810 | ```
811 |
812 | ## Utility Functions
813 |
814 |
815 |
816 | ### Log
817 |
818 | Modifies an error's stack to include the current stack and logs it to *stderr*. Useful for logging errors received by a callback.
819 |
820 | log(err[, message])
821 |
822 | __Arguments__
823 |
824 | * `err` - any error or error message received from a callback
825 | * `message` - any message you'd like to prepend
826 |
827 | ```js
828 | // Example
829 | mysql.query('SELECT * `FROM` users', function(err, results){
830 | if(err) return errors.log(err, "Had trouble retrieving users.");
831 | console.log(results);
832 | });
833 | ```
834 |
835 |
836 |
837 | ### prependCurrentStack
838 |
839 | Modifies an error's stack to include the current stack without logging it. Useful for logging errors received by a callback.
840 |
841 | prependCurrentStack(err)
842 |
843 | __Arguments__
844 |
845 | * `err` - any error or error message received from a callback
846 |
847 | ```js
848 | // Example
849 | mysql.query('SELECT * `FROM` users', function(err, results){
850 | if(err) {
851 | return errors.prependCurrentStack(err); // caller has better idea of source of err
852 | }
853 | console.log(results);
854 | });
855 | ```
856 |
857 |
858 |
859 | ### generateClass
860 |
861 | Simple interface for generating a new Error class type.
862 |
863 | helpers.generateClass(name[, options])
864 |
865 | __Arguments__
866 |
867 | * `name` - The full name of the new Error class
868 | * `options`
869 | * `extends` - The base class for the new Error class. Default is `Error`.
870 | * `globalize` - Boolean (default `true`) to store the Error in global space so that the Error is equivalent to others included from other versions of the module.
871 | * `args` - Array of names of values to accept and store from the class constructor. Default is `['message', 'inner_error']`.
872 | * `generateMessage` - A function for defining a custom error message.
873 |
874 | ```js
875 | // Example
876 | var ArgumentNullError = helpers.generateClass("ArgumentNullError", {
877 | extends: ArgumentError,
878 | args: ['argumentName'],
879 | generateMessage: function(){
880 | return "Missing argument: " + this.argumentName;
881 | }
882 | });
883 |
884 | throw new ArgumentNullError("username");
885 | ```
886 |
887 |
888 | ## Express Middleware Functions
889 |
890 |
891 |
892 | ### Crash Protector
893 |
894 | Express middleware for preventing the web server from crashing when an error is thrown from an asynchronous context.
895 | Any error that would have caused a crash is logged to *stderr*.
896 |
897 | ```js
898 | // Example
899 | var app = express();
900 |
901 | app.use(express.static(__dirname + '/../public'));
902 | app.use(express.bodyParser());
903 | app.use(errors.middleware.crashProtector());
904 |
905 | //insert new middleware here
906 |
907 | app.get('/healthcheck', function (req, res, next){res.send('YESOK')});
908 |
909 | app.use(app.router);
910 | app.use(errors.middleware.errorHandler);
911 |
912 | module.exports = app;
913 | ```
914 |
915 |
916 |
917 | ### Error Handler
918 |
919 | Express middleware that translates common errors into HTTP status codes and messages.
920 |
921 | ```js
922 | // Example
923 | var app = express();
924 |
925 | app.use(express.static(__dirname + '/../public'));
926 | app.use(express.bodyParser());
927 | app.use(errors.middleware.crashProtector());
928 |
929 | //insert new middleware here
930 |
931 | app.get('/healthcheck', function (req, res, next){res.send('YESOK')});
932 |
933 | app.use(app.router);
934 | app.use(errors.middleware.errorHandler);
935 |
936 | module.exports = app;
937 | ```
938 |
939 | ## Authors
940 |
941 | This library was developed by David Fenster at [Shutterstock](http://www.shutterstock.com)
942 |
943 | ## Contribute
944 |
945 | Please do! Check out our [Contributing guidelines](CONTRIBUTING.md).
946 |
947 | ## License
948 |
949 | [MIT](LICENSE) © 2013-2017 Shutterstock Images, LLC
950 |
--------------------------------------------------------------------------------
/common.js:
--------------------------------------------------------------------------------
1 | var exports = module.exports = {
2 | helpers: {
3 | generateClass: require('./lib/helpers/class-generator')
4 | },
5 | };
6 |
7 | exports.AlreadyInUseError = exports.AlreadyInUse = require('./lib/alreadyInUse');
8 | exports.ArgumentError = exports.Argument = require('./lib/argument');
9 | exports.ArgumentNullError = exports.ArgumentNull = require('./lib/argumentNull');
10 | exports.AuthenticationRequiredError = exports.AuthenticationRequired = require('./lib/authenticationRequired');
11 | exports.ConnectionError = exports.helpers.generateClass('ConnectionError');
12 | exports.Error = exports.helpers.generateClass('Error');
13 | exports.CommonError = Error;
14 | exports.HttpStatusError = exports.HttpStatus = require('./lib/http-status');
15 | exports.InvalidOperationError = require('./lib/invalid-operation');
16 | exports.NotFoundError = require('./lib/not-found');
17 | exports.NotImplementedError = exports.helpers.generateClass('NotImplementedError'),
18 | exports.NotSupportedError = exports.NotSupported = require('./lib/not-supported');
19 | exports.NotPermittedError = exports.NotPermitted = require('./lib/notPermitted');
20 | exports.OutOfMemoryError = exports.helpers.generateClass('OutOfMemoryError');
21 | exports.RangeError = exports.helpers.generateClass('RangeError', { extends: RangeError });
22 | exports.ReferenceError = exports.helpers.generateClass('ReferenceError', { extends: ReferenceError });
23 | exports.StackOverflowError = exports.helpers.generateClass('StackOverflowError');
24 | exports.SyntaxError = exports.helpers.generateClass('SyntaxError', { extends: SyntaxError });
25 | exports.TimeoutError = require('./lib/timeout.js')
26 | exports.TypeError = exports.helpers.generateClass('TypeError', { extends: TypeError });
27 | exports.URIError = exports.helpers.generateClass('URIError', { extends: URIError });
28 | exports.ValidationError = exports.Validation = require('./lib/validation');
29 |
30 | exports.io = {
31 | IOError: require('./lib/io/io')
32 | };
33 | exports.io.DirectoryNotFoundError = exports.helpers.generateClass('DirectoryNotFoundError', { extends: exports.io.IOError });
34 | exports.io.DriveNotFoundError = exports.helpers.generateClass('DriveNotFoundError', { extends: exports.io.IOError });
35 | exports.io.EndOfStreamError = exports.helpers.generateClass('EndOfStreamError', { extends: exports.io.IOError });
36 | exports.io.FileLoadError = require('./lib/io/file-load');
37 | exports.io.FileNotFoundError = require('./lib/io/file-not-found');
38 | exports.io.SocketError = exports.helpers.generateClass('SocketError', { extends: exports.io.IOError });
39 |
40 | exports.data = {
41 | DataError: require('./lib/data/data')
42 | };
43 | exports.data.MemcachedError = exports.helpers.generateClass('MemcachedError', { extends: exports.data.DataError });
44 | exports.data.MongoDBError = exports.helpers.generateClass('MongoDBError', { extends: exports.data.DataError });
45 | exports.data.RedisError = exports.helpers.generateClass('RedisError', { extends: exports.data.DataError });
46 | exports.data.RollbackError = exports.helpers.generateClass('RollbackError', { extends: exports.data.DataError });
47 | exports.data.SQLError = exports.helpers.generateClass('SQLError', { extends: exports.data.DataError });
48 | exports.data.TransactionError = exports.helpers.generateClass('TransactionError', { extends: exports.data.DataError });
49 |
50 |
51 |
52 | exports.Generic = exports.helpers.generateClass('GenericError'); //deprecated
53 |
54 |
55 | var logErrorDeprecationWarning = false;
56 | module.exports.logError = function(err, cb) {
57 | if (!logErrorDeprecationWarning) console.warn("logError is deprecated. Use log instead.");
58 | logErrorDeprecationWarning = true;
59 |
60 | if (err && !err.isLogged) {
61 | err.isLogged = true;
62 | console.error(err);
63 | }
64 | if (cb) cb(err);
65 | };
66 |
67 | module.exports.log = function(err, message) {
68 | if (typeof err == 'string') {
69 | err = new module.exports.Error(err);
70 | } else {
71 | if (message) {
72 | err.message = message;
73 | }
74 | err = module.exports.prependCurrentStack(err, 3);
75 | }
76 | if (err) {
77 | console.error(err && err.stack || err);
78 | err.isLogged = true;
79 | }
80 | return err;
81 | }
82 |
83 | module.exports.prependCurrentStack = function(err, offset_) {
84 | var linesToSkip = (typeof offset_ === 'undefined') ? 2 : offset_;
85 | var stackToPrepend = (new Error()).stack.split("\n").slice(linesToSkip);
86 | var mainStack = (err.stack || '').split("\n");
87 | var errTitle = mainStack.shift();
88 | err.stack = [errTitle].concat(stackToPrepend, "====", mainStack).join("\n");
89 | return err;
90 | };
91 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./common');
2 |
3 | module.exports.middleware = {
4 | errorHandler: require('./lib/middleware/errorHandler'),
5 | crashProtector: require('./lib/middleware/crashProtector')
6 | };
7 |
--------------------------------------------------------------------------------
/lib/alreadyInUse.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("AlreadyInUseError", {
3 | args: ['entity_name', 'arg1', 'arg2', 'arg3', 'arg4'],
4 | generateMessage: function(){
5 | var args = Array.prototype.slice.call(this.args, 1);
6 | return "The specified '" + this.entity_name + "' value is already in use for: " + args.join(', ');
7 | }
8 | })
9 |
--------------------------------------------------------------------------------
/lib/argument.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("ArgumentError", {
3 | args: ['argumentName', 'inner_error'],
4 | generateMessage: function(){
5 | return "Invalid or missing argument supplied: " + this.argumentName;
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/lib/argumentNull.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("ArgumentNullError", {
3 | args: ['argumentName', 'inner_error'],
4 | extends: require('./argument'),
5 | generateMessage: function(){
6 | return "Missing argument: " + this.argumentName;
7 | }
8 | })
9 |
--------------------------------------------------------------------------------
/lib/authenticationRequired.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("AuthenticationRequiredError", {
3 | args: ['message', 'inner_error'],
4 | generateMessage: function(){
5 | return "An attempt was made to perform an operation without authentication: " + this.message;
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/lib/data/data.js:
--------------------------------------------------------------------------------
1 | module.exports = require('../helpers/class-generator')('DataError');
--------------------------------------------------------------------------------
/lib/data/status-codes.js:
--------------------------------------------------------------------------------
1 | /* A dump of current https://nodejs.org/docs/latest/api/http.html#http_http_status_codes to avoid including native node modules in browser usage */
2 | module.exports = {
3 | '100': 'Continue',
4 | '101': 'Switching Protocols',
5 | '102': 'Processing',
6 | '103': 'Early Hints',
7 | '200': 'OK',
8 | '201': 'Created',
9 | '202': 'Accepted',
10 | '203': 'Non-Authoritative Information',
11 | '204': 'No Content',
12 | '205': 'Reset Content',
13 | '206': 'Partial Content',
14 | '207': 'Multi-Status',
15 | '208': 'Already Reported',
16 | '226': 'IM Used',
17 | '300': 'Multiple Choices',
18 | '301': 'Moved Permanently',
19 | '302': 'Found',
20 | '303': 'See Other',
21 | '304': 'Not Modified',
22 | '305': 'Use Proxy',
23 | '307': 'Temporary Redirect',
24 | '308': 'Permanent Redirect',
25 | '400': 'Bad Request',
26 | '401': 'Unauthorized',
27 | '402': 'Payment Required',
28 | '403': 'Forbidden',
29 | '404': 'Not Found',
30 | '405': 'Method Not Allowed',
31 | '406': 'Not Acceptable',
32 | '407': 'Proxy Authentication Required',
33 | '408': 'Request Timeout',
34 | '409': 'Conflict',
35 | '410': 'Gone',
36 | '411': 'Length Required',
37 | '412': 'Precondition Failed',
38 | '413': 'Payload Too Large',
39 | '414': 'URI Too Long',
40 | '415': 'Unsupported Media Type',
41 | '416': 'Range Not Satisfiable',
42 | '417': 'Expectation Failed',
43 | '418': 'I\'m a Teapot',
44 | '421': 'Misdirected Request',
45 | '422': 'Unprocessable Entity',
46 | '423': 'Locked',
47 | '424': 'Failed Dependency',
48 | '425': 'Unordered Collection',
49 | '426': 'Upgrade Required',
50 | '428': 'Precondition Required',
51 | '429': 'Too Many Requests',
52 | '431': 'Request Header Fields Too Large',
53 | '451': 'Unavailable For Legal Reasons',
54 | '500': 'Internal Server Error',
55 | '501': 'Not Implemented',
56 | '502': 'Bad Gateway',
57 | '503': 'Service Unavailable',
58 | '504': 'Gateway Timeout',
59 | '505': 'HTTP Version Not Supported',
60 | '506': 'Variant Also Negotiates',
61 | '507': 'Insufficient Storage',
62 | '508': 'Loop Detected',
63 | '509': 'Bandwidth Limit Exceeded',
64 | '510': 'Not Extended',
65 | '511': 'Network Authentication Required'
66 | };
67 |
--------------------------------------------------------------------------------
/lib/helpers/class-generator.js:
--------------------------------------------------------------------------------
1 | var globalize = require('../internal/globalize');
2 |
3 | module.exports = function generateErrorClass(name, options){
4 | options = options || {};
5 | if(options.subclass) console.warn("options.subclass is deprecated. use options.extends instead.");
6 | options.extends = options.extends || options.subclass || Error;
7 | options.args = options.args || ['message', 'inner_error'];
8 | options.generateMessage = options.generateMessage || null;
9 | options.globalize = options.globalize === false ? false : true;
10 |
11 | validateInput(name);
12 | validateArrayInput(options.args);
13 |
14 | var classConstructor = function classConstructor(){
15 | if(this.global_initialize) this.global_initialize(Class);
16 |
17 | this.args = arguments;
18 | for(var i = 0; i= 500 ? 500 : 400];
37 | this.message = message || http_message;
38 | if(!this.stack) Error.captureStackTrace(this, HttpStatusError);
39 | if(message) this.stack = http_message + "\n" + this.stack;
40 | }
41 |
42 | HttpStatusError.prototype = Object.create(Error.prototype);
43 | HttpStatusError.prototype.constructor = HttpStatusError;
44 |
45 | var code_map = HttpStatusError.code_map = {
46 | "ValidationError": 400,
47 | "ArgumentError": 400,
48 | "AuthenticationRequiredError": 401,
49 | "NotPermittedError": 403,
50 | "ArgumentNullError": function(err, req){
51 | var method = req && req.method || 'GET';
52 | var params = req && req.params || {};
53 | var route_path = req && req.route && req.route.path || '';
54 |
55 | if(/GET|HEAD/i.test(method) || params.hasOwnProperty(err.argumentName) || new RegExp(":" + err.argumentName + '').test(route_path + '/')) err.status_code = 404;
56 | else err.status_code = 400;
57 | err.message = err.message.replace(new RegExp("^Missing argument: (" + err.argumentName + ")$"), 'Not Found: "$1"' );
58 | },
59 | "NotFoundError": 404,
60 | "NotSupportedError": 405,
61 | "AlreadyInUseError": 409,
62 | };
63 |
64 | var codes = {};
65 | Object.keys(STATUS_CODES).forEach(function(key){
66 | codes[key] = STATUS_CODES[key];
67 | });
68 | var message_map = HttpStatusError.message_map = codes;
69 |
70 | module.exports = HttpStatusError;
71 |
--------------------------------------------------------------------------------
/lib/internal/globalize.js:
--------------------------------------------------------------------------------
1 | var key = "__COMMON-ERRORS-TYPES__";
2 | var global_errors = global[key] = global[key] || {};
3 |
4 | module.exports = function global_extend(Class) {
5 | Class.__original_prototype__ = Class.prototype;
6 | var global_class = global_errors[Class.name] = global_errors[Class.name] || Class;
7 | Class.prototype = Class.__global_prototype__ = global_class.prototype;
8 | Class.prototype.global_initialize = Class.prototype.global_initialize || function global_initialize(Class){
9 | var proto_keys = Object.keys(Class.__original_prototype__);
10 | for(var i = 0; i= 4) {
26 | errorHandler = middleware;
27 | break;
28 | } else if(app.router === middleware.handle) foundRouter = true;
29 | }
30 | return errorHandler;
31 | } catch(e) {
32 | console.error("Crash protector error", e);
33 | }
34 | }
--------------------------------------------------------------------------------
/lib/middleware/errorHandler.js:
--------------------------------------------------------------------------------
1 | var HttpStatusError = require('../http-status');
2 |
3 | module.exports = function errorHandler(err, req, res, next){
4 | if(!err) {
5 | if(next) return next();
6 | else return res.end();
7 | }
8 |
9 | err = new HttpStatusError(err, req);
10 | if(err.status_code >= 500) {
11 | console.error(err.stack);
12 | err.message = HttpStatusError.message_map[500]; //hide the real error from user agent.
13 | }
14 |
15 | res.status(err.status_code).send(err.message);
16 | }
17 |
--------------------------------------------------------------------------------
/lib/not-found.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("NotFoundError", {
3 | args: ['entity_name', 'inner_error'],
4 | generateMessage: function(){
5 | return 'Not Found: "' + this.entity_name + '"';
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/lib/not-supported.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("NotSupportedError", {
3 | args: ['message', 'inner_error'],
4 | generateMessage: function(){
5 | return "Not Supported: " + this.message;
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/lib/notPermitted.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("NotPermittedError", {
3 | args: ['message', 'inner_error'],
4 | generateMessage: function(){
5 | return "An attempt was made to perform an operation that is not permitted: " + this.message;
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/lib/timeout.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | module.exports = generateClass("TimeoutError", {
3 | args: ['time', 'inner_error'],
4 | generateMessage: function(){
5 | if(/^\d/.test(this.time)) return "Timeout of '" + this.time + "' exceeded";
6 | else return "Timeout exceeded: " + this.time;
7 | }
8 | })
9 |
--------------------------------------------------------------------------------
/lib/validation.js:
--------------------------------------------------------------------------------
1 | var generateClass = require('./helpers/class-generator');
2 | var ArgumentError = require('./argument');
3 |
4 | var ValidationError = module.exports = generateClass("ValidationError", {
5 | args: ['message', 'code', 'field']
6 | });
7 |
8 | ValidationError.prototype.addError = function addError(error) {
9 | this.errors = this.errors || [];
10 | this.errors.push(error);
11 | return this;
12 | }
13 |
14 | ValidationError.prototype.addErrors = function addErrors(errors) {
15 | if(!(errors instanceof Array)) throw new ArgumentError("errors");
16 |
17 | this.errors = this.errors || [];
18 | Array.prototype.push.apply(this.errors, errors);
19 | return this;
20 | }
21 |
22 | ValidationError.prototype.generateMessage = function generateMessage(){
23 | return this.message || "Validation failed.";
24 | }
25 |
26 | ValidationError.prototype.toJSON = function toJSON(){
27 | var o = {};
28 | if(this.errors) {
29 | if(this.message) o.message = this.message;
30 | o.errors = this.errors.map(function(error){
31 | return error.toJSON();
32 | });
33 | } else {
34 | if(this.message) o.text = this.message;
35 | if(this.code) o.code = this.code;
36 | if(this.field) o.field = this.field;
37 | }
38 | return o;
39 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "common-errors",
3 | "author": "David Fenster ",
4 | "description": "Common error classes and utility functions",
5 | "version": "1.2.0",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/shutterstock/node-common-errors.git"
9 | },
10 | "license": "MIT",
11 | "dependencies": {},
12 | "devDependencies": {
13 | "bluebird": "^3.5.0",
14 | "body-parser": "^1.17.2",
15 | "common-errors": "git://github.com/shutterstock/node-common-errors.git#v1.0.2",
16 | "express": "4.x.x",
17 | "express3": "git://github.com/dfenster/express3.git",
18 | "mocha": "^3.5.0",
19 | "sinon": "^3.0.0",
20 | "supertest": "^3.0.0"
21 | },
22 | "keywords": [
23 | "error",
24 | "errors",
25 | "common errors",
26 | "exception",
27 | "exceptions",
28 | "validation",
29 | "standard",
30 | "argument",
31 | "null",
32 | "database",
33 | "data",
34 | "mysql",
35 | "sql",
36 | "db",
37 | "memcached",
38 | "redis",
39 | "transaction",
40 | "rollback",
41 | "connection",
42 | "status codes",
43 | "log",
44 | "crash",
45 | "error handler"
46 | ],
47 | "scripts": {
48 | "test": "mocha --recursive tests"
49 | },
50 | "main": "index.js",
51 | "module": "common.js",
52 | "engines": {
53 | "node": ">=0.8"
54 | },
55 | "homepage": "https://github.com/shutterstock/node-common-errors",
56 | "bugs": "https://github.com/shutterstock/node-common-errors/issues",
57 | "contributors": [
58 | "David Fenster ",
59 | "Ben Kovacevich ",
60 | "Richard Littauer ",
61 | "Elliot Foster ",
62 | "Mark Stosberg ",
63 | "Ilya Shaisultanov ",
64 | "Mark ",
65 | "Michael Giuliana ",
66 | "skhvan1111 "
67 | ]
68 | }
69 |
--------------------------------------------------------------------------------
/tests/already-in-use.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var Promise = require('bluebird');
3 | var errors = require('..');
4 | var name = "AlreadyInUseError";
5 | var Err = errors[name];
6 |
7 | describe(name, function(){
8 | it("should work", function(){
9 | var error = new Err("Entity", 'att1', 'att2', 'att3', 'att4');
10 | assert.equal(error.name, name), 'Its name is correct.';
11 | assert.equal(error.message, "The specified 'Entity' value is already in use for: att1, att2, att3, att4");
12 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
13 | assert.ok(error instanceof Error, "It is an instanceof Error");
14 |
15 | var caught_error_in_promise = false;
16 | var promise = new Promise(function(res, rej) { res(true); }).then(function(){
17 | throw new Err("test error");
18 | }).catch(Error, function(e){
19 | caught_error_in_promise = true;
20 | }).finally(function(){
21 | assert.ok(caught_error_in_promise, "caught promise error");
22 | });
23 |
24 | });
25 | });
26 |
27 |
--------------------------------------------------------------------------------
/tests/argument-null.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('ArgumentNullError', {
3 | message: "arg1",
4 | message_to_assert: "Missing argument: arg1",
5 | extends: require('../lib/argument')
6 | });
--------------------------------------------------------------------------------
/tests/argument.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('ArgumentError', {
3 | message: "arg1",
4 | message_to_assert: "Invalid or missing argument supplied: arg1"
5 | });
--------------------------------------------------------------------------------
/tests/authentication-required.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('AuthenticationRequiredError', {
3 | message: "password is incorrect",
4 | message_to_assert: "An attempt was made to perform an operation without authentication: password is incorrect"
5 | });
--------------------------------------------------------------------------------
/tests/connection.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('ConnectionError');
--------------------------------------------------------------------------------
/tests/data/data.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('DataError', {
3 | full_name: 'data.DataError'
4 | });
--------------------------------------------------------------------------------
/tests/data/memcached.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('MemcachedError', {
3 | full_name: 'data.MemcachedError',
4 | extends: require('../../lib/data/data')
5 | });
--------------------------------------------------------------------------------
/tests/data/mongodb.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('MongoDBError', {
3 | full_name: 'data.MongoDBError',
4 | extends: require('../../lib/data/data')
5 | });
--------------------------------------------------------------------------------
/tests/data/redis.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('RedisError', {
3 | full_name: 'data.RedisError',
4 | extends: require('../../lib/data/data')
5 | });
--------------------------------------------------------------------------------
/tests/data/rollback.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('RollbackError', {
3 | full_name: 'data.RollbackError',
4 | extends: require('../../lib/data/data')
5 | });
--------------------------------------------------------------------------------
/tests/data/sql.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('SQLError', {
3 | full_name: 'data.SQLError',
4 | extends: require('../../lib/data/data')
5 | });
--------------------------------------------------------------------------------
/tests/data/transaction.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('TransactionError', {
3 | full_name: 'data.TransactionError',
4 | extends: require('../../lib/data/data')
5 | });
--------------------------------------------------------------------------------
/tests/error.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('Error');
--------------------------------------------------------------------------------
/tests/helpers/class-generator.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var classGenerator = require('../../lib/helpers/class-generator');
3 | var errors = require('../../');
4 |
5 | describe('classGenerator', function(){
6 | it("should work", function(){
7 | var Err = classGenerator("Err", {args: ['message', 'inner_error', 'arg1', 'arg2']});
8 | assert.ok(Err, 'Error returned');
9 | assert.equal(Err.length, 4, "has proper constructor arguments");
10 | assert.equal(Err.super_, Error, "is instanceof Error");
11 | assert.equal(Err.prototype instanceof Error, true, "is instanceof Error");
12 | assert.equal(Err.name, "Err", "has proper name");
13 | });
14 |
15 | it('should be safe to use a name - strings only', function(){
16 | var caught_error;
17 | try {
18 | var Err = classGenerator(2);
19 | } catch(e) {
20 | caught_error = e;
21 | }
22 | assert.ok(caught_error, "using a non-string is unsafe.");
23 | });
24 |
25 | it('should be safe to use a name - word characters only', function(){
26 | var caught_error;
27 | try {
28 | var Err = classGenerator("New Error");
29 | } catch(e) {
30 | caught_error = e;
31 | }
32 | assert.ok(caught_error, "using a non-string is unsafe.");
33 | });
34 |
35 | it('should be safe to use custom arguments - array only', function(){
36 | var caught_error;
37 | try {
38 | var Err = classGenerator("NewError", {args: {}});
39 | } catch(e) {
40 | caught_error = e;
41 | }
42 | assert.ok(caught_error, "using a non-array is unsafe.");
43 | });
44 |
45 | it('should be safe to use custom arguments - array of strings only', function(){
46 | var caught_error;
47 | try {
48 | var Err = classGenerator("NewError", {args: ['arg1', 2]});
49 | } catch(e) {
50 | caught_error = e;
51 | }
52 | assert.ok(caught_error, "using a non-strings in args array is unsafe");
53 | });
54 |
55 | it('should be safe to use custom arguments - array of strings only', function(){
56 | var caught_error;
57 | try {
58 | var Err = classGenerator("NewError", {args: ['arg1', 'arg 2']});
59 | } catch(e) {
60 | caught_error = e;
61 | }
62 | assert.ok(caught_error, "using non-word characters in args array is unsafe");
63 | });
64 |
65 | it('should globalize errors', function(){
66 | var GlobalError = classGenerator("SomeError");
67 | var GlobalError2 = classGenerator("SomeError");
68 | var LocalError = classGenerator("SomeError", {globalize: false});
69 |
70 | assert.ok(new GlobalError() instanceof Error);
71 | assert.ok(new GlobalError2() instanceof Error);
72 | assert.ok(new LocalError() instanceof Error);
73 | assert.ok(new GlobalError() instanceof GlobalError2);
74 | assert.ok(new GlobalError2() instanceof GlobalError);
75 | assert.ok(!(new GlobalError() instanceof LocalError));
76 | });
77 | });
78 |
--------------------------------------------------------------------------------
/tests/helpers/util.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var errors = require('../../');
3 | var EventEmitter = require('events').EventEmitter;
4 |
5 | describe('prependCurrentStack', function(){
6 | it("should work", function(){
7 | var event = new EventEmitter();
8 | function foo(cb) {
9 | return bar(cb);
10 | }
11 | function bar(cb) {
12 | return cb(new Error("Inner Error"));
13 | }
14 |
15 | event.on('error', function final(err){
16 | errors.prependCurrentStack(err);
17 | assert.ok(err, "Got an error");
18 | var stack_split = err.stack.split('===');
19 | assert.ok(/Error: Inner Error\n\s*at EventEmitter.final.*/.test(stack_split[0]));
20 | assert.ok(/\n\s*at bar.*\n\s*at foo/.test(stack_split[1]), "Stack is good");
21 | });
22 |
23 | foo(function callback(err){
24 | process.nextTick(function emitEvent(){
25 | event.emit('error', err);
26 | })
27 | })
28 | });
29 | });
30 |
31 | describe("global namespace", function(){
32 | it("should maintain a global namespace for instanceof", function(){
33 | var external_errors = require('common-errors');
34 | var TestError = errors.helpers.generateClass('Error');
35 | var err = new errors.Error("This is an error");
36 | var external_err = new external_errors.Error("This is an error");
37 | var test_err = new TestError("This is an error");
38 |
39 | assert.notEqual(err.stack, test_err.stack, 'err and new err stacks are not equal');
40 | assert.notEqual(err.stack, external_err.stack, 'err and external err stacks are not equal');
41 | assert.notEqual(test_err.stack, external_err.stack, 'new err and external err stacks are not equal');
42 | assert.equal(err.stack.replace(/:\d+:\d+/, ''), test_err.stack.replace(/:\d+:\d+/, ''), 'err and new err have almost the same stack');
43 | assert.equal(err.stack.replace(/:\d+:\d+/, ''), external_err.stack.replace(/:\d+:\d+/, ''), 'err and external err have almost the same stack');
44 | assert.equal(test_err.stack.replace(/:\d+:\d+/, ''), external_err.stack.replace(/:\d+:\d+/, ''), 'new err and external error have almost the same stack');
45 |
46 | assert.ok(err instanceof errors.Error, 'err instanceof its own class');
47 | assert.ok(err instanceof TestError, 'err instanceof a new Error');
48 | assert.ok(err instanceof external_errors.Error, 'err instanceof an external Error');
49 | assert.ok(test_err instanceof errors.Error, 'new err instanceof Error');
50 | assert.ok(test_err instanceof TestError, 'new err instanceof itself');
51 | assert.ok(test_err instanceof external_errors.Error, 'new err instanceof an external Error');
52 | assert.ok(external_err instanceof errors.Error, 'external error instanceof Error');
53 | assert.ok(external_err instanceof TestError, 'external error instanceof new Error');
54 | assert.ok(external_err instanceof external_errors.Error, 'external error instanceof itself');
55 | });
56 | });
57 |
58 |
59 |
--------------------------------------------------------------------------------
/tests/http-status.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var HttpStatusError = require('../').HttpStatusError;
3 |
4 | describe("HttpStatusError", function(){
5 | function performBasicAssertions(error){
6 | assert.equal(error.name, "HttpStatusError"), 'Its name is correct.';
7 | assert.ok(new RegExp(error.name + ": " + error.message.replace(/\)/g, '\\)').replace(/\(/g, '\\(') + "\n(.*\n)+").test(error.stack), "Stack is good");
8 | assert.ok(error instanceof Error, Error, "It is an instanceof Error");
9 | }
10 |
11 | it("should work with status code and message", function(){
12 | var error = new HttpStatusError(403, "You got a 403");
13 | assert.equal(error.message, "You got a 403");
14 | assert.equal(error.status, 403);
15 | assert.equal(error.status_code, 403);
16 | assert.equal(error.statusCode, 403);
17 | performBasicAssertions(error);
18 | });
19 |
20 | it("should work with status code", function(){
21 | var error = new HttpStatusError(403);
22 | assert.equal(error.message, "(403) Forbidden");
23 | assert.equal(error.name, "HttpStatusError");
24 | assert.equal(error.status, 403);
25 | assert.equal(error.status_code, 403);
26 | assert.equal(error.statusCode, 403);
27 | performBasicAssertions(error);
28 | });
29 |
30 | it("should work with status code and message without new", function(){
31 | var error = HttpStatusError(403, "You got a 403");
32 | assert.equal(error.message, "You got a 403");
33 | assert.equal(error.status, 403);
34 | assert.equal(error.status_code, 403);
35 | assert.equal(error.statusCode, 403);
36 | performBasicAssertions(error);
37 | });
38 |
39 | it("should work with status code without new", function(){
40 | var error = HttpStatusError(403);
41 | assert.equal(error.message, "(403) Forbidden");
42 | assert.equal(error.status, 403);
43 | assert.equal(error.status_code, 403);
44 | assert.equal(error.statusCode, 403);
45 | performBasicAssertions(error);
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/tests/invalid-operation.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('InvalidOperationError', {
3 | message_to_assert: "Invalid Operation: test message"
4 | });
--------------------------------------------------------------------------------
/tests/io/directory-not-found.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('DirectoryNotFoundError', {
3 | full_name: 'io.DirectoryNotFoundError',
4 | extends: require('../../lib/io/io')
5 | });
--------------------------------------------------------------------------------
/tests/io/drive-not-found.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('DriveNotFoundError', {
3 | full_name: 'io.DriveNotFoundError',
4 | extends: require('../../lib/io/io')
5 | });
--------------------------------------------------------------------------------
/tests/io/end-of-stream.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('EndOfStreamError', {
3 | full_name: 'io.EndOfStreamError',
4 | extends: require('../../lib/io/io')
5 | });
--------------------------------------------------------------------------------
/tests/io/file-load.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('FileLoadError', {
3 | full_name: 'io.FileLoadError',
4 | extends: require('../../lib/io/io'),
5 | message_to_assert: "Unable to load file: test message"
6 | });
--------------------------------------------------------------------------------
/tests/io/file-not-found.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('FileNotFoundError', {
3 | full_name: 'io.FileNotFoundError',
4 | extends: require('../../lib/io/io'),
5 | message_to_assert: "File not found: test message"
6 | });
--------------------------------------------------------------------------------
/tests/io/io.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('IOError', {
3 | full_name: 'io.IOError'
4 | });
--------------------------------------------------------------------------------
/tests/io/socket.js:
--------------------------------------------------------------------------------
1 | var support = require('../support');
2 | support.testError('SocketError', {
3 | full_name: 'io.SocketError',
4 | extends: require('../../lib/io/io')
5 | });
--------------------------------------------------------------------------------
/tests/log.js:
--------------------------------------------------------------------------------
1 | var errors = require('../');
2 | var assert = require('assert');
3 |
4 | describe("errors.log", function(){
5 |
6 | var consoleFunctions = {};
7 | Object.keys(console).forEach(function(key){
8 | consoleFunctions[key] = console[key];
9 | });
10 |
11 | var errorLog;
12 |
13 | beforeEach(function(cb){
14 | errorLog = [];
15 |
16 | console.error = function(message){
17 | if(message && message.message) errorLog.push(message.message);
18 | else errorLog.push(message);
19 | };
20 |
21 | cb();
22 | });
23 |
24 | afterEach(function(cb){
25 | Object.keys(consoleFunctions).forEach(function(key){
26 | console[key] = consoleFunctions[key];
27 | });
28 | cb();
29 | })
30 |
31 | var logAnError = function (err, message) {
32 | return errors.log(err, message)
33 | }
34 |
35 | it("should log a message", function(){
36 | var err = new Error("This is a assert.");
37 | var err2 = logAnError(err, "Panic!");
38 | assert.equal(errorLog.length, 1);
39 | assert.ok(/Error: Panic!/.test(errorLog[0]), 'message matches');
40 | assert.ok(err2.isLogged);
41 | assert.ok(err2 instanceof Error, 'we have a javascript error object');
42 |
43 | var stack = err2.stack.split("\n");
44 | assert.ok(/logAnError/.test(stack[1]), 'we prepend the current stack trace');
45 | var splitterIndex = stack.indexOf('====');
46 | assert.ok(splitterIndex, 'we spit the stacks with "===="');
47 | assert.ok(/Context\./.test(stack.slice(splitterIndex)[1]), 'we keep the old stack trace');
48 | });
49 |
50 | it("log string error", function(){
51 | var err2 = logAnError("Panic!");
52 | assert.equal(errorLog.length, 1);
53 | assert.ok(/Error: Panic!/.test(errorLog[0]), 'message matches');
54 | assert.ok(err2.isLogged);
55 | assert.ok(err2 instanceof errors.Error, 'we have an error');
56 | assert.ok(!/====[ ]/.test(errorLog[0]), "we don't prepend any stack traces");
57 | })
58 |
59 | it("log error, no message", function(){
60 | var err = new Error("This is a assert.");
61 | var err2 = logAnError(err);
62 | assert.equal(errorLog.length, 1);
63 | assert.ok(/Error: This is a assert./.test(errorLog[0]), "message matches");
64 |
65 | var stack = err2.stack.split("\n");
66 | assert.ok(/logAnError/.test(stack[1]), 'we prepend the current stack trace');
67 | var splitterIndex = stack.indexOf('====');
68 | assert.ok(splitterIndex, 'we spit the stacks with "===="');
69 | assert.ok(/Context\./.test(stack.slice(splitterIndex)[1]), 'we keep the old stack trace');
70 |
71 | assert.ok(err2 instanceof Error, 'we have a javascript error object');
72 | assert.ok(err2.isLogged);
73 | })
74 |
75 | it("log generic error", function(){
76 | var err = new errors.Generic("This is a assert.");
77 | var err2 = logAnError(err);
78 | assert.equal(errorLog.length, 1);
79 | assert.ok(/GenericError: This is a assert./.test(errorLog[0]), "message matches");
80 | assert.ok(err2 instanceof errors.Generic, 'we have a generic error');
81 | assert.ok(err2.isLogged);
82 |
83 | var stack = err2.stack.split("\n");
84 | assert.ok(/logAnError/.test(stack[1]), 'we prepend the current stack trace');
85 | var splitterIndex = stack.indexOf('====');
86 | assert.ok(splitterIndex, 'we spit the stacks with "===="');
87 | assert.ok(/Context\./.test(stack.slice(splitterIndex)[1]), 'we keep the old stack trace');
88 | });
89 | })
--------------------------------------------------------------------------------
/tests/middleware/errorHandler.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var sinon = require('sinon');
3 | var supertest = require('supertest');
4 | var express3 = require('express3');
5 | var express4 = require('express');
6 | var body_parser = require('body-parser');
7 | var errors = require('../../');
8 | var errorHandler = errors.middleware.errorHandler;
9 |
10 | var sandbox = sinon.sandbox.create();
11 |
12 | describe("errorHandler", function(){
13 | var err;
14 |
15 | var app = new express4();
16 | app.use(body_parser.json());
17 | app.all('/error', function(req, res, next){ return next(err); });
18 | app.post('/error/:test', function(req, res, next){ return next(err); });
19 | app.use(errorHandler);
20 | var request = new supertest(app);
21 |
22 | beforeEach(function(){
23 | sandbox.stub(console, 'error').callsFake(function(message){ });
24 | });
25 |
26 | afterEach(function(){
27 | sandbox.restore();
28 | })
29 |
30 | it("should handle NotPermittedError", function(done){
31 | err = new errors.NotPermitted("don't do that");
32 | request.get('/error').end(function(err, res){
33 | assert.equal(res.res.statusCode, 403);
34 | assert.equal(res.text, "An attempt was made to perform an operation that is not permitted: don't do that");
35 | assert.ok(!console.error.called, "console.error not called");
36 | done();
37 | });
38 | });
39 |
40 | it("should handle AuthenticationRequired", function(done){
41 | err = new errors.AuthenticationRequired("gime password");
42 | request.get('/error').end(function(err, res){
43 | assert.equal(res.res.statusCode, 401);
44 | assert.equal(res.text, "An attempt was made to perform an operation without authentication: gime password");
45 | assert.ok(!console.error.called, "console.error not called");
46 | done();
47 | });
48 | });
49 |
50 | it("should handle Validation", function(done){
51 | err = new errors.Validation("bad")
52 | request.get('/error').end(function(err, res){
53 | assert.equal(res.res.statusCode, 400);
54 | assert.equal(res.text, "bad");
55 | assert.ok(!console.error.called, "console.error not called");
56 | done();
57 | });
58 | });
59 |
60 | it("should handle AlreadyInUse", function(done){
61 | err = new errors.AlreadyInUse("bad", "test");
62 | request.get('/error').end(function(err, res){
63 | assert.equal(res.res.statusCode, 409);
64 | assert.equal(res.text, "The specified 'bad' value is already in use for: test");
65 | assert.ok(!console.error.called, "console.error not called");
66 | done();
67 | });
68 | });
69 |
70 | it("should handle ArgumentNull", function(done){
71 | err = new errors.ArgumentNull("test");
72 | request.get('/error').end(function(err, res){
73 | assert.equal(res.res.statusCode, 404);
74 | assert.equal(res.text, "Not Found: \"test\"");
75 | assert.ok(!console.error.called, "console.error not called");
76 | done();
77 | });
78 | });
79 |
80 | it("should handle ArgumentNull route param", function(done){
81 | err = new errors.ArgumentNull("test");
82 | request.post('/error/1').end(function(err, res){
83 | assert.equal(res.res.statusCode, 404);
84 | assert.equal(res.text, "Not Found: \"test\"");
85 | assert.ok(!console.error.called, "console.error not called");
86 | done();
87 | });
88 | });
89 |
90 | it("should handle ArgumentNull route param in express3", function(done){
91 | err = new errors.ArgumentNull("test");
92 |
93 | var app = express3();
94 | app.use(app.router)
95 | app.use(errorHandler);
96 | app.post('/error/:test', function(req, res, next){
97 | return next(err);
98 | });
99 |
100 | var request = new supertest(app);
101 |
102 | request.post('/error/1').end(function(err, res){
103 | assert.equal(res.res.statusCode, 404);
104 | assert.equal(res.text, "Not Found: \"test\"");
105 | assert.ok(!console.error.called, "console.error not called");
106 | done();
107 | });
108 | });
109 |
110 | it("should handle ArgumentNull POST", function(done){
111 | err = new errors.ArgumentNull("test");
112 | request.post('/error').send({test:1}).end(function(err, res){
113 | assert.equal(res.res.statusCode, 400);
114 | assert.equal(res.text, "Not Found: \"test\"");
115 | assert.ok(!console.error.called, "console.error not called");
116 | done();
117 | });
118 | });
119 |
120 | it("should handle NotFoundError", function(done){
121 | err = new errors.NotFoundError("test");
122 | request.get('/error').end(function(err, res){
123 | assert.equal(res.res.statusCode, 404);
124 | assert.equal(res.text, "Not Found: \"test\"");
125 | assert.ok(!console.error.called, "console.error not called");
126 | done();
127 | });
128 | });
129 |
130 | it("should handle Error", function(done){
131 | err = new Error("test");
132 | request.get('/error').end(function(err, res){
133 | assert.equal(res.res.statusCode, 500);
134 | assert.equal(res.text, "Internal Server Error");
135 | assert.ok(console.error.called);
136 | assert.ok(/test/.test(console.error.getCall(0).args[0]));
137 | done();
138 | });
139 | });
140 |
141 | it("should handle Error status", function(done){
142 | err = new Error("test");
143 | err.status = 544;
144 | request.get('/error').end(function(err, res){
145 | assert.equal(res.res.statusCode, 544);
146 | assert.equal(res.text, "Internal Server Error");
147 | assert.ok(console.error.called);
148 | assert.ok(/test/.test(console.error.getCall(0).args[0]));
149 | done();
150 | });
151 | });
152 |
153 | it("should handle Error status", function(done){
154 | err = new Error("test");
155 | err.statusCode = 544;
156 | request.get('/error').end(function(err, res){
157 | assert.equal(res.res.statusCode, 544);
158 | assert.equal(res.text, "Internal Server Error");
159 | assert.ok(console.error.called);
160 | assert.ok(/test/.test(console.error.getCall(0).args[0]));
161 | done();
162 | });
163 | });
164 |
165 | it("should handle Error status", function(done){
166 | err = new Error("test");
167 | err.status_code = 544;
168 | request.get('/error').end(function(err, res){
169 | assert.equal(res.res.statusCode, 544);
170 | assert.equal(res.text, "Internal Server Error");
171 | assert.ok(console.error.called);
172 | assert.ok(/test/.test(console.error.getCall(0).args[0]));
173 | done();
174 | });
175 | });
176 |
177 | it("should handle HttpStatusError (deprecated)", function(done){
178 | err = new errors.HttpStatus('custom status message', 544);
179 | request.get('/error').end(function(err, res){
180 | assert.equal(res.res.statusCode, 544);
181 | assert.equal(res.text, "Internal Server Error");
182 | assert.ok(console.error.called);
183 | assert.ok(/custom status message/.test(console.error.getCall(0).args[0]));
184 | done();
185 | });
186 | });
187 |
188 | it("should handle HttpStatusError", function(done){
189 | err = new errors.HttpStatus(544, 'custom status message')
190 | request.get('/error').end(function(err, res){
191 | assert.equal(res.res.statusCode, 544);
192 | assert.equal(res.text, "Internal Server Error");
193 | assert.ok(console.error.called);
194 | assert.ok(/custom status message/.test(console.error.getCall(0).args[0]));
195 | done();
196 | });
197 | });
198 |
199 | it("should handle HttpStatusError 400", function(done){
200 | err = new errors.HttpStatus(444, 'custom status message')
201 | request.get('/error').end(function(err, res){
202 | assert.equal(res.res.statusCode, 444);
203 | assert.equal(res.text, "custom status message");
204 | assert.ok(!console.error.called);
205 | done();
206 | });
207 | });
208 |
209 | it("should work with express 3", function(done){
210 | var app = express3();
211 | app.use(app.router)
212 | app.use(errorHandler);
213 | app.get('/error', function(req, res, next){
214 | return next(new Error("This is a test"));
215 | });
216 |
217 | var request = new supertest(app);
218 | request.get('/error')
219 | .end(function(err, res){
220 | assert.equal(res.res.statusCode, 500);
221 | done();
222 | })
223 | })
224 |
225 | });
226 |
--------------------------------------------------------------------------------
/tests/not-found.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('NotFoundError', {
3 | message: "entity name",
4 | message_to_assert: 'Not Found: "entity name"'
5 | });
--------------------------------------------------------------------------------
/tests/not-implemented.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('NotImplementedError');
--------------------------------------------------------------------------------
/tests/not-permitted.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('NotPermittedError', {
3 | message_to_assert: "An attempt was made to perform an operation that is not permitted: test message"
4 | });
--------------------------------------------------------------------------------
/tests/not-supported.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('NotSupportedError', {
3 | message_to_assert: "Not Supported: test message"
4 | });
--------------------------------------------------------------------------------
/tests/out-of-memory.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('OutOfMemoryError');
--------------------------------------------------------------------------------
/tests/range.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('RangeError', { extends: RangeError });
--------------------------------------------------------------------------------
/tests/reference.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('ReferenceError', { extends: ReferenceError });
--------------------------------------------------------------------------------
/tests/stack-overflow.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('StackOverflowError');
--------------------------------------------------------------------------------
/tests/support/index.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var errors = require('../..');
3 | var Promise = require('bluebird');
4 |
5 | module.exports.testError = function testError(name, opts){
6 | opts = opts || {};
7 | opts.message = opts.message || "test message";
8 | opts.message_to_assert = opts.message_to_assert || opts.message;
9 | opts.extends = opts.extends || Error;
10 | opts.full_name = opts.full_name || name;
11 |
12 | function performAssertions(Err, error) {
13 | assert.equal(error.name, name), 'Its name is correct.';
14 | assert.equal(error.message, opts.message_to_assert);
15 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
16 | assert.equal(Err.super_.name, opts.extends.name, "It is an instance of" + opts.extends.name);
17 | var sampleError = new Err(error);
18 | assert.equal(sampleError.name, name, "Has the expected type " + name);
19 | assert.ok(error instanceof Error, "It is an instanceof Error");
20 | assert.ok(error instanceof opts.extends, "It is an instanceof " + opts.extends.name);
21 |
22 | var caught_error_in_promise = false;
23 | var promise = new Promise(function(res, rej) { res(true); }).then(function(){
24 | throw new Err("test error");
25 | }).catch(opts.extends, function(e){
26 | caught_error_in_promise = true;
27 | }).finally(function(){
28 | assert.ok(caught_error_in_promise, "caught promise error");
29 | });
30 | }
31 |
32 | describe(name, function(){
33 | var Err = errors;
34 | (opts.full_name).split('.').forEach(function(dir){ Err = Err[dir]; });
35 |
36 | it("should work", function(){
37 | assert.ok(Err, name + " exists.");
38 | var inner_error = new Error("inner error");
39 | var error = new Err(opts.message);
40 |
41 | performAssertions(Err, error);
42 | });
43 |
44 | it("should work without new", function(){
45 | assert.ok(Err, name + " exists.");
46 | var inner_error = new Error("inner error");
47 | var error = Err(opts.message);
48 |
49 | performAssertions(Err, error);
50 | });
51 | });
52 | }
53 |
--------------------------------------------------------------------------------
/tests/syntax.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('SyntaxError', { extends: SyntaxError });
--------------------------------------------------------------------------------
/tests/timeout.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var errors = require('..');
3 | var name = "TimeoutError";
4 | var Err = errors[name];
5 |
6 | describe(name, function(){
7 | it("should work for durations", function(){
8 | var error = new Err(100);
9 | assert.equal(error.name, name), 'Its name is correct.';
10 | assert.equal(error.message, "Timeout of '100' exceeded");
11 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
12 | assert.ok(error instanceof Error, "It is an instanceof Error");
13 | });
14 |
15 | it("should work", function(){
16 | var error = new Err("query took too long");
17 | assert.equal(error.name, name), 'Its name is correct.';
18 | assert.equal(error.message, "Timeout exceeded: query took too long");
19 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
20 | assert.ok(error instanceof Error, "It is an instanceof Error");
21 | });
22 |
23 | });
24 |
--------------------------------------------------------------------------------
/tests/type.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('TypeError', { extends: TypeError });
--------------------------------------------------------------------------------
/tests/uri.js:
--------------------------------------------------------------------------------
1 | var support = require('./support');
2 | support.testError('URIError', { extends: URIError });
--------------------------------------------------------------------------------
/tests/validation.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var errors = require('..');
3 | var name = "ValidationError";
4 | var Err = errors[name];
5 |
6 | describe(name, function(){
7 | it("should work", function(){
8 | var error = new Err("This is a validation message.", 'VAL_CODE_1', 'name');
9 | assert.equal(error.name, name), 'Its name is correct.';
10 | assert.equal(error.message, "This is a validation message.");
11 | assert.equal(error.field, "name");
12 | assert.deepEqual(error.toJSON(), {"text":"This is a validation message.","field":"name","code":"VAL_CODE_1"});
13 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
14 | assert.ok(error instanceof Error, "It is an instanceof Error");
15 | });
16 |
17 | describe("nested errors", function(){
18 | it("should addError", function(){
19 | var error = new Err().addError(new Err("This is a validation message.", 'VAL_CODE_1', 'name'));
20 | assert.equal(error.name, name), 'Its name is correct.';
21 | assert.equal(error.message, "Validation failed.");
22 | assert.deepEqual(error.toJSON(), {
23 | message: "Validation failed.",
24 | errors: [{
25 | "text":"This is a validation message.",
26 | "field":"name",
27 | "code":"VAL_CODE_1"
28 | }]
29 | });
30 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
31 | assert.ok(error instanceof Error, "It is an instanceof Error");
32 | });
33 |
34 | it("should addErrors", function(){
35 | var error = new Err().addErrors([new Err("This is a validation message.", 'VAL_CODE_1', 'name')]);
36 | assert.equal(error.name, name), 'Its name is correct.';
37 | assert.equal(error.message, "Validation failed.");
38 | assert.deepEqual(error.toJSON(), {
39 | message: "Validation failed.",
40 | errors: [{
41 | "text":"This is a validation message.",
42 | "field":"name",
43 | "code":"VAL_CODE_1"
44 | }]
45 | });
46 | assert.ok(new RegExp(error.name + ": " + error.message + "\n(.*\n)+").test(error.stack), "Stack is good");
47 | assert.ok(error instanceof Error, "It is an instanceof Error");
48 | });
49 |
50 | it("should require an Array for addErrors", function(){
51 | var caught_error;
52 | try {
53 | var error = new Err().addErrors(1);
54 | } catch(e) {
55 | caught_error = e;
56 | }
57 |
58 | assert.ok(caught_error instanceof errors['ArgumentError'])
59 | });
60 | });
61 | });
62 |
--------------------------------------------------------------------------------