• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Module dependencies.
3 */
4
5const tty = require('tty');
6const util = require('util');
7
8/**
9 * This is the Node.js implementation of `debug()`.
10 */
11
12exports.init = init;
13exports.log = log;
14exports.formatArgs = formatArgs;
15exports.save = save;
16exports.load = load;
17exports.useColors = useColors;
18exports.destroy = util.deprecate(
19	() => {},
20	'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
21);
22
23/**
24 * Colors.
25 */
26
27exports.colors = [6, 2, 3, 4, 5, 1];
28
29try {
30	// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
31	// eslint-disable-next-line import/no-extraneous-dependencies
32	const supportsColor = require('supports-color');
33
34	if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
35		exports.colors = [
36			20,
37			21,
38			26,
39			27,
40			32,
41			33,
42			38,
43			39,
44			40,
45			41,
46			42,
47			43,
48			44,
49			45,
50			56,
51			57,
52			62,
53			63,
54			68,
55			69,
56			74,
57			75,
58			76,
59			77,
60			78,
61			79,
62			80,
63			81,
64			92,
65			93,
66			98,
67			99,
68			112,
69			113,
70			128,
71			129,
72			134,
73			135,
74			148,
75			149,
76			160,
77			161,
78			162,
79			163,
80			164,
81			165,
82			166,
83			167,
84			168,
85			169,
86			170,
87			171,
88			172,
89			173,
90			178,
91			179,
92			184,
93			185,
94			196,
95			197,
96			198,
97			199,
98			200,
99			201,
100			202,
101			203,
102			204,
103			205,
104			206,
105			207,
106			208,
107			209,
108			214,
109			215,
110			220,
111			221
112		];
113	}
114} catch (error) {
115	// Swallow - we only care if `supports-color` is available; it doesn't have to be.
116}
117
118/**
119 * Build up the default `inspectOpts` object from the environment variables.
120 *
121 *   $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
122 */
123
124exports.inspectOpts = Object.keys(process.env).filter(key => {
125	return /^debug_/i.test(key);
126}).reduce((obj, key) => {
127	// Camel-case
128	const prop = key
129		.substring(6)
130		.toLowerCase()
131		.replace(/_([a-z])/g, (_, k) => {
132			return k.toUpperCase();
133		});
134
135	// Coerce string value into JS value
136	let val = process.env[key];
137	if (/^(yes|on|true|enabled)$/i.test(val)) {
138		val = true;
139	} else if (/^(no|off|false|disabled)$/i.test(val)) {
140		val = false;
141	} else if (val === 'null') {
142		val = null;
143	} else {
144		val = Number(val);
145	}
146
147	obj[prop] = val;
148	return obj;
149}, {});
150
151/**
152 * Is stdout a TTY? Colored output is enabled when `true`.
153 */
154
155function useColors() {
156	return 'colors' in exports.inspectOpts ?
157		Boolean(exports.inspectOpts.colors) :
158		tty.isatty(process.stderr.fd);
159}
160
161/**
162 * Adds ANSI color escape codes if enabled.
163 *
164 * @api public
165 */
166
167function formatArgs(args) {
168	const {namespace: name, useColors} = this;
169
170	if (useColors) {
171		const c = this.color;
172		const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
173		const prefix = `  ${colorCode};1m${name} \u001B[0m`;
174
175		args[0] = prefix + args[0].split('\n').join('\n' + prefix);
176		args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
177	} else {
178		args[0] = getDate() + name + ' ' + args[0];
179	}
180}
181
182function getDate() {
183	if (exports.inspectOpts.hideDate) {
184		return '';
185	}
186	return new Date().toISOString() + ' ';
187}
188
189/**
190 * Invokes `util.format()` with the specified arguments and writes to stderr.
191 */
192
193function log(...args) {
194	return process.stderr.write(util.format(...args) + '\n');
195}
196
197/**
198 * Save `namespaces`.
199 *
200 * @param {String} namespaces
201 * @api private
202 */
203function save(namespaces) {
204	if (namespaces) {
205		process.env.DEBUG = namespaces;
206	} else {
207		// If you set a process.env field to null or undefined, it gets cast to the
208		// string 'null' or 'undefined'. Just delete instead.
209		delete process.env.DEBUG;
210	}
211}
212
213/**
214 * Load `namespaces`.
215 *
216 * @return {String} returns the previously persisted debug modes
217 * @api private
218 */
219
220function load() {
221	return process.env.DEBUG;
222}
223
224/**
225 * Init logic for `debug` instances.
226 *
227 * Create a new `inspectOpts` object in case `useColors` is set
228 * differently for a particular `debug` instance.
229 */
230
231function init(debug) {
232	debug.inspectOpts = {};
233
234	const keys = Object.keys(exports.inspectOpts);
235	for (let i = 0; i < keys.length; i++) {
236		debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
237	}
238}
239
240module.exports = require('./common')(exports);
241
242const {formatters} = module.exports;
243
244/**
245 * Map %o to `util.inspect()`, all on a single line.
246 */
247
248formatters.o = function (v) {
249	this.inspectOpts.colors = this.useColors;
250	return util.inspect(v, this.inspectOpts)
251		.split('\n')
252		.map(str => str.trim())
253		.join(' ');
254};
255
256/**
257 * Map %O to `util.inspect()`, allowing multiple lines if needed.
258 */
259
260formatters.O = function (v) {
261	this.inspectOpts.colors = this.useColors;
262	return util.inspect(v, this.inspectOpts);
263};
264