1 | var util = require('util');
|
2 | var colors = require('ansi-colors');
|
3 |
|
4 | var nonEnum = ['message', 'name', 'stack'];
|
5 | var ignored = new Set(
|
6 | nonEnum.concat([
|
7 | '__safety',
|
8 | '_stack',
|
9 | 'plugin',
|
10 | 'showProperties',
|
11 | 'showStack',
|
12 | 'domain',
|
13 | 'domainEmitter',
|
14 | 'domainThrown',
|
15 | ])
|
16 | );
|
17 | var props = [
|
18 | 'fileName',
|
19 | 'lineNumber',
|
20 | 'message',
|
21 | 'name',
|
22 | 'plugin',
|
23 | 'showProperties',
|
24 | 'showStack',
|
25 | 'stack',
|
26 | ];
|
27 |
|
28 | function PluginError(plugin, message, options) {
|
29 | if (!(this instanceof PluginError)) {
|
30 | return new PluginError(plugin, message, options);
|
31 | }
|
32 |
|
33 | Error.call(this);
|
34 | var opts = setDefaults(plugin, message, options);
|
35 | var self = this;
|
36 |
|
37 |
|
38 | if (typeof opts.error === 'object') {
|
39 | var keys = new Set(Object.keys(opts.error).concat(nonEnum));
|
40 |
|
41 |
|
42 | keys.forEach(function (prop) {
|
43 | self[prop] = opts.error[prop];
|
44 | });
|
45 | }
|
46 |
|
47 |
|
48 | props.forEach(function (prop) {
|
49 | if (prop in opts) {
|
50 | this[prop] = opts[prop];
|
51 | }
|
52 | }, this);
|
53 |
|
54 |
|
55 | if (!this.stack) {
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | var safety = {};
|
66 | safety.toString = function () {
|
67 | return this._messageWithDetails() + '\nStack:';
|
68 | }.bind(this);
|
69 |
|
70 | Error.captureStackTrace(safety, arguments.callee || this.constructor);
|
71 | this.__safety = safety;
|
72 | }
|
73 | if (!this.plugin) {
|
74 | throw new Error('Missing plugin name');
|
75 | }
|
76 | if (!this.message) {
|
77 | throw new Error('Missing error message');
|
78 | }
|
79 | }
|
80 |
|
81 | util.inherits(PluginError, Error);
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | PluginError.prototype._messageWithDetails = function () {
|
88 | var msg = 'Message:\n ' + this.message;
|
89 | var details = this._messageDetails();
|
90 | if (details !== '') {
|
91 | msg += '\n' + details;
|
92 | }
|
93 | return msg;
|
94 | };
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 | PluginError.prototype._messageDetails = function () {
|
101 | if (!this.showProperties) {
|
102 | return '';
|
103 | }
|
104 |
|
105 | var props = Object.keys(this).filter(function (key) {
|
106 | return !ignored.has(key);
|
107 | });
|
108 | var len = props.length;
|
109 |
|
110 | if (len === 0) {
|
111 | return '';
|
112 | }
|
113 |
|
114 | var res = '';
|
115 | var i = 0;
|
116 | while (len--) {
|
117 | var prop = props[i++];
|
118 | res += ' ';
|
119 | res += prop + ': ' + this[prop];
|
120 | res += '\n';
|
121 | }
|
122 | return 'Details:\n' + res;
|
123 | };
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 | PluginError.prototype.toString = function () {
|
130 | var detailsWithStack = function (stack) {
|
131 | return this._messageWithDetails() + '\nStack:\n' + stack;
|
132 | }.bind(this);
|
133 |
|
134 | var msg = '';
|
135 | if (this.showStack) {
|
136 |
|
137 | if (this.__safety) {
|
138 | msg = this.__safety.stack;
|
139 | } else if (this._stack) {
|
140 | msg = detailsWithStack(this._stack);
|
141 | } else {
|
142 |
|
143 | msg = detailsWithStack(this.stack);
|
144 | }
|
145 | return message(msg, this);
|
146 | }
|
147 |
|
148 | msg = this._messageWithDetails();
|
149 | return message(msg, this);
|
150 | };
|
151 |
|
152 |
|
153 | function message(msg, thisArg) {
|
154 | var sig = colors.red(thisArg.name);
|
155 | sig += ' in plugin ';
|
156 | sig += '"' + colors.cyan(thisArg.plugin) + '"';
|
157 | sig += '\n';
|
158 | sig += msg;
|
159 | return sig;
|
160 | }
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 | function setDefaults(plugin, message, opts) {
|
167 | if (typeof plugin === 'object') {
|
168 | return defaults(plugin);
|
169 | }
|
170 | if (message instanceof Error) {
|
171 | opts = Object.assign({}, opts, { error: message });
|
172 | } else if (typeof message === 'object') {
|
173 | opts = Object.assign({}, message);
|
174 | } else {
|
175 | opts = Object.assign({}, opts, { message: message });
|
176 | }
|
177 | opts.plugin = plugin;
|
178 | return defaults(opts);
|
179 | }
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 | function defaults(opts) {
|
192 | return Object.assign(
|
193 | {
|
194 | showStack: false,
|
195 | showProperties: true,
|
196 | },
|
197 | opts
|
198 | );
|
199 | }
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 | module.exports = PluginError;
|