/ node_modules / debug / src / common.js
common.js
  1  
  2  /**
  3   * This is the common logic for both the Node.js and web browser
  4   * implementations of `debug()`.
  5   */
  6  
  7  function setup(env) {
  8  	createDebug.debug = createDebug;
  9  	createDebug.default = createDebug;
 10  	createDebug.coerce = coerce;
 11  	createDebug.disable = disable;
 12  	createDebug.enable = enable;
 13  	createDebug.enabled = enabled;
 14  	createDebug.humanize = require('ms');
 15  	createDebug.destroy = destroy;
 16  
 17  	Object.keys(env).forEach(key => {
 18  		createDebug[key] = env[key];
 19  	});
 20  
 21  	/**
 22  	* The currently active debug mode names, and names to skip.
 23  	*/
 24  
 25  	createDebug.names = [];
 26  	createDebug.skips = [];
 27  
 28  	/**
 29  	* Map of special "%n" handling functions, for the debug "format" argument.
 30  	*
 31  	* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
 32  	*/
 33  	createDebug.formatters = {};
 34  
 35  	/**
 36  	* Selects a color for a debug namespace
 37  	* @param {String} namespace The namespace string for the debug instance to be colored
 38  	* @return {Number|String} An ANSI color code for the given namespace
 39  	* @api private
 40  	*/
 41  	function selectColor(namespace) {
 42  		let hash = 0;
 43  
 44  		for (let i = 0; i < namespace.length; i++) {
 45  			hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
 46  			hash |= 0; // Convert to 32bit integer
 47  		}
 48  
 49  		return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
 50  	}
 51  	createDebug.selectColor = selectColor;
 52  
 53  	/**
 54  	* Create a debugger with the given `namespace`.
 55  	*
 56  	* @param {String} namespace
 57  	* @return {Function}
 58  	* @api public
 59  	*/
 60  	function createDebug(namespace) {
 61  		let prevTime;
 62  		let enableOverride = null;
 63  		let namespacesCache;
 64  		let enabledCache;
 65  
 66  		function debug(...args) {
 67  			// Disabled?
 68  			if (!debug.enabled) {
 69  				return;
 70  			}
 71  
 72  			const self = debug;
 73  
 74  			// Set `diff` timestamp
 75  			const curr = Number(new Date());
 76  			const ms = curr - (prevTime || curr);
 77  			self.diff = ms;
 78  			self.prev = prevTime;
 79  			self.curr = curr;
 80  			prevTime = curr;
 81  
 82  			args[0] = createDebug.coerce(args[0]);
 83  
 84  			if (typeof args[0] !== 'string') {
 85  				// Anything else let's inspect with %O
 86  				args.unshift('%O');
 87  			}
 88  
 89  			// Apply any `formatters` transformations
 90  			let index = 0;
 91  			args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
 92  				// If we encounter an escaped % then don't increase the array index
 93  				if (match === '%%') {
 94  					return '%';
 95  				}
 96  				index++;
 97  				const formatter = createDebug.formatters[format];
 98  				if (typeof formatter === 'function') {
 99  					const val = args[index];
100  					match = formatter.call(self, val);
101  
102  					// Now we need to remove `args[index]` since it's inlined in the `format`
103  					args.splice(index, 1);
104  					index--;
105  				}
106  				return match;
107  			});
108  
109  			// Apply env-specific formatting (colors, etc.)
110  			createDebug.formatArgs.call(self, args);
111  
112  			const logFn = self.log || createDebug.log;
113  			logFn.apply(self, args);
114  		}
115  
116  		debug.namespace = namespace;
117  		debug.useColors = createDebug.useColors();
118  		debug.color = createDebug.selectColor(namespace);
119  		debug.extend = extend;
120  		debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
121  
122  		Object.defineProperty(debug, 'enabled', {
123  			enumerable: true,
124  			configurable: false,
125  			get: () => {
126  				if (enableOverride !== null) {
127  					return enableOverride;
128  				}
129  				if (namespacesCache !== createDebug.namespaces) {
130  					namespacesCache = createDebug.namespaces;
131  					enabledCache = createDebug.enabled(namespace);
132  				}
133  
134  				return enabledCache;
135  			},
136  			set: v => {
137  				enableOverride = v;
138  			}
139  		});
140  
141  		// Env-specific initialization logic for debug instances
142  		if (typeof createDebug.init === 'function') {
143  			createDebug.init(debug);
144  		}
145  
146  		return debug;
147  	}
148  
149  	function extend(namespace, delimiter) {
150  		const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
151  		newDebug.log = this.log;
152  		return newDebug;
153  	}
154  
155  	/**
156  	* Enables a debug mode by namespaces. This can include modes
157  	* separated by a colon and wildcards.
158  	*
159  	* @param {String} namespaces
160  	* @api public
161  	*/
162  	function enable(namespaces) {
163  		createDebug.save(namespaces);
164  		createDebug.namespaces = namespaces;
165  
166  		createDebug.names = [];
167  		createDebug.skips = [];
168  
169  		const split = (typeof namespaces === 'string' ? namespaces : '')
170  			.trim()
171  			.replace(/\s+/g, ',')
172  			.split(',')
173  			.filter(Boolean);
174  
175  		for (const ns of split) {
176  			if (ns[0] === '-') {
177  				createDebug.skips.push(ns.slice(1));
178  			} else {
179  				createDebug.names.push(ns);
180  			}
181  		}
182  	}
183  
184  	/**
185  	 * Checks if the given string matches a namespace template, honoring
186  	 * asterisks as wildcards.
187  	 *
188  	 * @param {String} search
189  	 * @param {String} template
190  	 * @return {Boolean}
191  	 */
192  	function matchesTemplate(search, template) {
193  		let searchIndex = 0;
194  		let templateIndex = 0;
195  		let starIndex = -1;
196  		let matchIndex = 0;
197  
198  		while (searchIndex < search.length) {
199  			if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
200  				// Match character or proceed with wildcard
201  				if (template[templateIndex] === '*') {
202  					starIndex = templateIndex;
203  					matchIndex = searchIndex;
204  					templateIndex++; // Skip the '*'
205  				} else {
206  					searchIndex++;
207  					templateIndex++;
208  				}
209  			} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
210  				// Backtrack to the last '*' and try to match more characters
211  				templateIndex = starIndex + 1;
212  				matchIndex++;
213  				searchIndex = matchIndex;
214  			} else {
215  				return false; // No match
216  			}
217  		}
218  
219  		// Handle trailing '*' in template
220  		while (templateIndex < template.length && template[templateIndex] === '*') {
221  			templateIndex++;
222  		}
223  
224  		return templateIndex === template.length;
225  	}
226  
227  	/**
228  	* Disable debug output.
229  	*
230  	* @return {String} namespaces
231  	* @api public
232  	*/
233  	function disable() {
234  		const namespaces = [
235  			...createDebug.names,
236  			...createDebug.skips.map(namespace => '-' + namespace)
237  		].join(',');
238  		createDebug.enable('');
239  		return namespaces;
240  	}
241  
242  	/**
243  	* Returns true if the given mode name is enabled, false otherwise.
244  	*
245  	* @param {String} name
246  	* @return {Boolean}
247  	* @api public
248  	*/
249  	function enabled(name) {
250  		for (const skip of createDebug.skips) {
251  			if (matchesTemplate(name, skip)) {
252  				return false;
253  			}
254  		}
255  
256  		for (const ns of createDebug.names) {
257  			if (matchesTemplate(name, ns)) {
258  				return true;
259  			}
260  		}
261  
262  		return false;
263  	}
264  
265  	/**
266  	* Coerce `val`.
267  	*
268  	* @param {Mixed} val
269  	* @return {Mixed}
270  	* @api private
271  	*/
272  	function coerce(val) {
273  		if (val instanceof Error) {
274  			return val.stack || val.message;
275  		}
276  		return val;
277  	}
278  
279  	/**
280  	* XXX DO NOT USE. This is a temporary stub function.
281  	* XXX It WILL be removed in the next major release.
282  	*/
283  	function destroy() {
284  		console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
285  	}
286  
287  	createDebug.enable(createDebug.load());
288  
289  	return createDebug;
290  }
291  
292  module.exports = setup;