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