second
[josuexyz/.git] / node_modules / debug / src / debug.js
1
2 /**
3  * This is the common logic for both the Node.js and web browser
4  * implementations of `debug()`.
5  *
6  * Expose `debug()` as the module.
7  */
8
9 exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
10 exports.coerce = coerce;
11 exports.disable = disable;
12 exports.enable = enable;
13 exports.enabled = enabled;
14 exports.humanize = require('ms');
15
16 /**
17  * The currently active debug mode names, and names to skip.
18  */
19
20 exports.names = [];
21 exports.skips = [];
22
23 /**
24  * Map of special "%n" handling functions, for the debug "format" argument.
25  *
26  * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
27  */
28
29 exports.formatters = {};
30
31 /**
32  * Previous log timestamp.
33  */
34
35 var prevTime;
36
37 /**
38  * Select a color.
39  * @param {String} namespace
40  * @return {Number}
41  * @api private
42  */
43
44 function selectColor(namespace) {
45   var hash = 0, i;
46
47   for (i in namespace) {
48     hash  = ((hash << 5) - hash) + namespace.charCodeAt(i);
49     hash |= 0; // Convert to 32bit integer
50   }
51
52   return exports.colors[Math.abs(hash) % exports.colors.length];
53 }
54
55 /**
56  * Create a debugger with the given `namespace`.
57  *
58  * @param {String} namespace
59  * @return {Function}
60  * @api public
61  */
62
63 function createDebug(namespace) {
64
65   function debug() {
66     // disabled?
67     if (!debug.enabled) return;
68
69     var self = debug;
70
71     // set `diff` timestamp
72     var curr = +new Date();
73     var ms = curr - (prevTime || curr);
74     self.diff = ms;
75     self.prev = prevTime;
76     self.curr = curr;
77     prevTime = curr;
78
79     // turn the `arguments` into a proper Array
80     var args = new Array(arguments.length);
81     for (var i = 0; i < args.length; i++) {
82       args[i] = arguments[i];
83     }
84
85     args[0] = exports.coerce(args[0]);
86
87     if ('string' !== typeof args[0]) {
88       // anything else let's inspect with %O
89       args.unshift('%O');
90     }
91
92     // apply any `formatters` transformations
93     var index = 0;
94     args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
95       // if we encounter an escaped % then don't increase the array index
96       if (match === '%%') return match;
97       index++;
98       var formatter = exports.formatters[format];
99       if ('function' === typeof formatter) {
100         var val = args[index];
101         match = formatter.call(self, val);
102
103         // now we need to remove `args[index]` since it's inlined in the `format`
104         args.splice(index, 1);
105         index--;
106       }
107       return match;
108     });
109
110     // apply env-specific formatting (colors, etc.)
111     exports.formatArgs.call(self, args);
112
113     var logFn = debug.log || exports.log || console.log.bind(console);
114     logFn.apply(self, args);
115   }
116
117   debug.namespace = namespace;
118   debug.enabled = exports.enabled(namespace);
119   debug.useColors = exports.useColors();
120   debug.color = selectColor(namespace);
121
122   // env-specific initialization logic for debug instances
123   if ('function' === typeof exports.init) {
124     exports.init(debug);
125   }
126
127   return debug;
128 }
129
130 /**
131  * Enables a debug mode by namespaces. This can include modes
132  * separated by a colon and wildcards.
133  *
134  * @param {String} namespaces
135  * @api public
136  */
137
138 function enable(namespaces) {
139   exports.save(namespaces);
140
141   exports.names = [];
142   exports.skips = [];
143
144   var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
145   var len = split.length;
146
147   for (var i = 0; i < len; i++) {
148     if (!split[i]) continue; // ignore empty strings
149     namespaces = split[i].replace(/\*/g, '.*?');
150     if (namespaces[0] === '-') {
151       exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
152     } else {
153       exports.names.push(new RegExp('^' + namespaces + '$'));
154     }
155   }
156 }
157
158 /**
159  * Disable debug output.
160  *
161  * @api public
162  */
163
164 function disable() {
165   exports.enable('');
166 }
167
168 /**
169  * Returns true if the given mode name is enabled, false otherwise.
170  *
171  * @param {String} name
172  * @return {Boolean}
173  * @api public
174  */
175
176 function enabled(name) {
177   var i, len;
178   for (i = 0, len = exports.skips.length; i < len; i++) {
179     if (exports.skips[i].test(name)) {
180       return false;
181     }
182   }
183   for (i = 0, len = exports.names.length; i < len; i++) {
184     if (exports.names[i].test(name)) {
185       return true;
186     }
187   }
188   return false;
189 }
190
191 /**
192  * Coerce `val`.
193  *
194  * @param {Mixed} val
195  * @return {Mixed}
196  * @api private
197  */
198
199 function coerce(val) {
200   if (val instanceof Error) return val.stack || val.message;
201   return val;
202 }