| 'use strict'; |
| |
| var util = require('util'); |
| var isArrayish = require('is-arrayish'); |
| |
| var errorEx = function errorEx(name, properties) { |
| if (!name || name.constructor !== String) { |
| properties = name || {}; |
| name = Error.name; |
| } |
| |
| var errorExError = function ErrorEXError(message) { |
| if (!this) { |
| return new ErrorEXError(message); |
| } |
| |
| message = message instanceof Error |
| ? message.message |
| : (message || this.message); |
| |
| Error.call(this, message); |
| Error.captureStackTrace(this, errorExError); |
| |
| this.name = name; |
| |
| Object.defineProperty(this, 'message', { |
| configurable: true, |
| enumerable: false, |
| get: function () { |
| var newMessage = message.split(/\r?\n/g); |
| |
| for (var key in properties) { |
| if (!properties.hasOwnProperty(key)) { |
| continue; |
| } |
| |
| var modifier = properties[key]; |
| |
| if ('message' in modifier) { |
| newMessage = modifier.message(this[key], newMessage) || newMessage; |
| if (!isArrayish(newMessage)) { |
| newMessage = [newMessage]; |
| } |
| } |
| } |
| |
| return newMessage.join('\n'); |
| }, |
| set: function (v) { |
| message = v; |
| } |
| }); |
| |
| var overwrittenStack = null; |
| |
| var stackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack'); |
| var stackGetter = stackDescriptor.get; |
| var stackValue = stackDescriptor.value; |
| delete stackDescriptor.value; |
| delete stackDescriptor.writable; |
| |
| stackDescriptor.set = function (newstack) { |
| overwrittenStack = newstack; |
| }; |
| |
| stackDescriptor.get = function () { |
| var stack = (overwrittenStack || ((stackGetter) |
| ? stackGetter.call(this) |
| : stackValue)).split(/\r?\n+/g); |
| |
| // starting in Node 7, the stack builder caches the message. |
| // just replace it. |
| if (!overwrittenStack) { |
| stack[0] = this.name + ': ' + this.message; |
| } |
| |
| var lineCount = 1; |
| for (var key in properties) { |
| if (!properties.hasOwnProperty(key)) { |
| continue; |
| } |
| |
| var modifier = properties[key]; |
| |
| if ('line' in modifier) { |
| var line = modifier.line(this[key]); |
| if (line) { |
| stack.splice(lineCount++, 0, ' ' + line); |
| } |
| } |
| |
| if ('stack' in modifier) { |
| modifier.stack(this[key], stack); |
| } |
| } |
| |
| return stack.join('\n'); |
| }; |
| |
| Object.defineProperty(this, 'stack', stackDescriptor); |
| }; |
| |
| if (Object.setPrototypeOf) { |
| Object.setPrototypeOf(errorExError.prototype, Error.prototype); |
| Object.setPrototypeOf(errorExError, Error); |
| } else { |
| util.inherits(errorExError, Error); |
| } |
| |
| return errorExError; |
| }; |
| |
| errorEx.append = function (str, def) { |
| return { |
| message: function (v, message) { |
| v = v || def; |
| |
| if (v) { |
| message[0] += ' ' + str.replace('%s', v.toString()); |
| } |
| |
| return message; |
| } |
| }; |
| }; |
| |
| errorEx.line = function (str, def) { |
| return { |
| line: function (v) { |
| v = v || def; |
| |
| if (v) { |
| return str.replace('%s', v.toString()); |
| } |
| |
| return null; |
| } |
| }; |
| }; |
| |
| module.exports = errorEx; |