├── test └── level.js ├── example.js ├── package.json ├── index.js ├── LICENSE └── README.md /test/level.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | var explain = require('../') 3 | var le = require('level-errors') 4 | 5 | var err = explain(new le.NotFoundError('weird'), 'could find it') 6 | assert.ok(err.notFound, 'error should have notFound') 7 | console.log('okay') 8 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var explain = require('./') 2 | 3 | function explainedError(cb) { 4 | require('fs').stat('neoatuhrcoahkrcophkr', function (err) { 5 | if(err) cb(explain(err, 'asked for a file that certainly did not exist')) 6 | else cb() 7 | }) 8 | } 9 | 10 | explainedError(function (err) { 11 | throw explain(err, 'called an function that was expected to fail') 12 | }) 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "explain-error", 3 | "description": "", 4 | "version": "1.0.4", 5 | "homepage": "https://github.com/dominictarr/explain-error", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/dominictarr/explain-error.git" 9 | }, 10 | "scripts": { 11 | "test": "set -e; for t in test/*.js; do node $t; done" 12 | }, 13 | "author": "Dominic Tarr (http://dominictarr.com)", 14 | "license": "MIT", 15 | "devDependencies": { 16 | "level-errors": "^1.0.4" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | function getStack(err) { 3 | if(err.stack && err.name && err.message) 4 | return err.stack.substring(err.name.length + 3 + err.message.length) 5 | .split('\n') 6 | else if(err.stack) 7 | return err.stack.split('\n') 8 | } 9 | 10 | function removePrefix (a, b) { 11 | return a.filter(function (e) { 12 | return !~b.indexOf(e) 13 | }) 14 | } 15 | 16 | var explain = module.exports = function (err, message) { 17 | if(!(err.stack && err.name && err.message)) { 18 | console.error(new Error('stackless error')) 19 | return err 20 | } 21 | 22 | var _err = new Error(message) 23 | var stack = removePrefix(getStack(_err).slice(1), getStack(err)).join('\n') 24 | 25 | _err.__proto__ = err 26 | 27 | _err.stack = 28 | _err.name + ': ' + _err.message + '\n' + 29 | stack + '\n ' + err.stack 30 | 31 | return _err 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Dominic Tarr 4 | 5 | Permission is hereby granted, free of charge, 6 | to any person obtaining a copy of this software and 7 | associated documentation files (the "Software"), to 8 | deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, 10 | merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom 12 | the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice 16 | shall be included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 22 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # explain-error 2 | 3 | wrap errors in explainations. 4 | 5 | In node sometimes something fails because of some internal detail, 6 | but then this error may be passed back somewhere else, too often, 7 | context is lost. 8 | 9 | ## example 10 | 11 | ``` js 12 | var explain = require('explain-error') 13 | 14 | //stat a file that does not exist. this will error, add an explaination. 15 | function explainedError(cb) { 16 | require('fs').stat('neoatuhrcoahkrcophkr', function (err) { 17 | if(err) cb(explain(err, 'asked for a file that certainly did not exist')) 18 | else cb() 19 | }) 20 | } 21 | 22 | //show that this works even with multiple layers of explainations. 23 | explainedError(function (err) { 24 | throw explain(err, 'called an function that was expected to fail') 25 | }) 26 | ``` 27 | 28 | output: 29 | 30 | `fs.stat` does not show where it was called from, 31 | but at least now you know what happened after that. 32 | 33 | ``` 34 | Error: called an function that was expected to fail 35 | at /home/dominic/c/explain-error/example.js:11:9 36 | at /home/dominic/c/explain-error/example.js:5:13 37 | Error: asked for a file that certainly did not exist 38 | at /home/dominic/c/explain-error/example.js:5:16 39 | at Object.oncomplete (fs.js:107:15) 40 | Error: ENOENT, stat neoatuhrcoahkrcophkr 41 | 42 | ``` 43 | 44 | ## parsing stack traces 45 | 46 | of course, this adds lines to your errors that will do not look like normal js errors. 47 | will this break all your tools? if so please post an issue. 48 | 49 | ## License 50 | 51 | MIT 52 | --------------------------------------------------------------------------------