3 * This is the common logic for both the Node.js and web browser
4 * implementations of `debug()`.
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');
16 Object.keys(env).forEach(key => {
17 createDebug[key] = env[key];
21 * Active `debug` instances.
23 createDebug.instances = [];
26 * The currently active debug mode names, and names to skip.
29 createDebug.names = [];
30 createDebug.skips = [];
33 * Map of special "%n" handling functions, for the debug "format" argument.
35 * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
37 createDebug.formatters = {};
40 * Selects a color for a debug namespace
41 * @param {String} namespace The namespace string for the for the debug instance to be colored
42 * @return {Number|String} An ANSI color code for the given namespace
45 function selectColor(namespace) {
48 for (let i = 0; i < namespace.length; i++) {
49 hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
50 hash |= 0; // Convert to 32bit integer
53 return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
55 createDebug.selectColor = selectColor;
58 * Create a debugger with the given `namespace`.
60 * @param {String} namespace
64 function createDebug(namespace) {
67 function debug(...args) {
75 // Set `diff` timestamp
76 const curr = Number(new Date());
77 const ms = curr - (prevTime || curr);
83 args[0] = createDebug.coerce(args[0]);
85 if (typeof args[0] !== 'string') {
86 // Anything else let's inspect with %O
90 // Apply any `formatters` transformations
92 args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
93 // If we encounter an escaped % then don't increase the array index
98 const formatter = createDebug.formatters[format];
99 if (typeof formatter === 'function') {
100 const val = args[index];
101 match = formatter.call(self, val);
103 // Now we need to remove `args[index]` since it's inlined in the `format`
104 args.splice(index, 1);
110 // Apply env-specific formatting (colors, etc.)
111 createDebug.formatArgs.call(self, args);
113 const logFn = self.log || createDebug.log;
114 logFn.apply(self, args);
117 debug.namespace = namespace;
118 debug.enabled = createDebug.enabled(namespace);
119 debug.useColors = createDebug.useColors();
120 debug.color = selectColor(namespace);
121 debug.destroy = destroy;
122 debug.extend = extend;
123 // Debug.formatArgs = formatArgs;
124 // debug.rawLog = rawLog;
126 // env-specific initialization logic for debug instances
127 if (typeof createDebug.init === 'function') {
128 createDebug.init(debug);
131 createDebug.instances.push(debug);
137 const index = createDebug.instances.indexOf(this);
139 createDebug.instances.splice(index, 1);
145 function extend(namespace, delimiter) {
146 const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
147 newDebug.log = this.log;
152 * Enables a debug mode by namespaces. This can include modes
153 * separated by a colon and wildcards.
155 * @param {String} namespaces
158 function enable(namespaces) {
159 createDebug.save(namespaces);
161 createDebug.names = [];
162 createDebug.skips = [];
165 const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
166 const len = split.length;
168 for (i = 0; i < len; i++) {
170 // ignore empty strings
174 namespaces = split[i].replace(/\*/g, '.*?');
176 if (namespaces[0] === '-') {
177 createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
179 createDebug.names.push(new RegExp('^' + namespaces + '$'));
183 for (i = 0; i < createDebug.instances.length; i++) {
184 const instance = createDebug.instances[i];
185 instance.enabled = createDebug.enabled(instance.namespace);
190 * Disable debug output.
192 * @return {String} namespaces
197 ...createDebug.names.map(toNamespace),
198 ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
200 createDebug.enable('');
205 * Returns true if the given mode name is enabled, false otherwise.
207 * @param {String} name
211 function enabled(name) {
212 if (name[name.length - 1] === '*') {
219 for (i = 0, len = createDebug.skips.length; i < len; i++) {
220 if (createDebug.skips[i].test(name)) {
225 for (i = 0, len = createDebug.names.length; i < len; i++) {
226 if (createDebug.names[i].test(name)) {
235 * Convert regexp to namespace
237 * @param {RegExp} regxep
238 * @return {String} namespace
241 function toNamespace(regexp) {
242 return regexp.toString()
243 .substring(2, regexp.toString().length - 2)
244 .replace(/\.\*\?$/, '*');
254 function coerce(val) {
255 if (val instanceof Error) {
256 return val.stack || val.message;
261 createDebug.enable(createDebug.load());
266 module.exports = setup;