UNPKG

2.91 kBJavaScriptView Raw
1'use strict';
2
3var util = require('util');
4var isArrayish = require('is-arrayish');
5
6var errorEx = function errorEx(name, properties) {
7 if (!name || name.constructor !== String) {
8 properties = name || {};
9 name = Error.name;
10 }
11
12 var errorExError = function ErrorEXError(message) {
13 if (!this) {
14 return new ErrorEXError(message);
15 }
16
17 message = message instanceof Error
18 ? message.message
19 : (message || this.message);
20
21 Error.call(this, message);
22 Error.captureStackTrace(this, errorExError);
23
24 this.name = name;
25
26 Object.defineProperty(this, 'message', {
27 configurable: true,
28 enumerable: false,
29 get: function () {
30 var newMessage = message.split(/\r?\n/g);
31
32 for (var key in properties) {
33 if (!properties.hasOwnProperty(key)) {
34 continue;
35 }
36
37 var modifier = properties[key];
38
39 if ('message' in modifier) {
40 newMessage = modifier.message(this[key], newMessage) || newMessage;
41 if (!isArrayish(newMessage)) {
42 newMessage = [newMessage];
43 }
44 }
45 }
46
47 return newMessage.join('\n');
48 },
49 set: function (v) {
50 message = v;
51 }
52 });
53
54 var overwrittenStack = null;
55
56 var stackDescriptor = Object.getOwnPropertyDescriptor(this, 'stack');
57 var stackGetter = stackDescriptor.get;
58 var stackValue = stackDescriptor.value;
59 delete stackDescriptor.value;
60 delete stackDescriptor.writable;
61
62 stackDescriptor.set = function (newstack) {
63 overwrittenStack = newstack;
64 };
65
66 stackDescriptor.get = function () {
67 var stack = (overwrittenStack || ((stackGetter)
68 ? stackGetter.call(this)
69 : stackValue)).split(/\r?\n+/g);
70
71 // starting in Node 7, the stack builder caches the message.
72 // just replace it.
73 if (!overwrittenStack) {
74 stack[0] = this.name + ': ' + this.message;
75 }
76
77 var lineCount = 1;
78 for (var key in properties) {
79 if (!properties.hasOwnProperty(key)) {
80 continue;
81 }
82
83 var modifier = properties[key];
84
85 if ('line' in modifier) {
86 var line = modifier.line(this[key]);
87 if (line) {
88 stack.splice(lineCount++, 0, ' ' + line);
89 }
90 }
91
92 if ('stack' in modifier) {
93 modifier.stack(this[key], stack);
94 }
95 }
96
97 return stack.join('\n');
98 };
99
100 Object.defineProperty(this, 'stack', stackDescriptor);
101 };
102
103 if (Object.setPrototypeOf) {
104 Object.setPrototypeOf(errorExError.prototype, Error.prototype);
105 Object.setPrototypeOf(errorExError, Error);
106 } else {
107 util.inherits(errorExError, Error);
108 }
109
110 return errorExError;
111};
112
113errorEx.append = function (str, def) {
114 return {
115 message: function (v, message) {
116 v = v || def;
117
118 if (v) {
119 message[0] += ' ' + str.replace('%s', v.toString());
120 }
121
122 return message;
123 }
124 };
125};
126
127errorEx.line = function (str, def) {
128 return {
129 line: function (v) {
130 v = v || def;
131
132 if (v) {
133 return str.replace('%s', v.toString());
134 }
135
136 return null;
137 }
138 };
139};
140
141module.exports = errorEx;