Spaces:
Running
Running
/** | |
* This is the common logic for both the Node.js and web browser | |
* implementations of `debug()`. | |
*/ | |
function setup(env) { | |
createDebug.debug = createDebug; | |
createDebug.default = createDebug; | |
createDebug.coerce = coerce; | |
createDebug.disable = disable; | |
createDebug.enable = enable; | |
createDebug.enabled = enabled; | |
createDebug.humanize = require('ms'); | |
createDebug.destroy = destroy; | |
Object.keys(env).forEach(key => { | |
createDebug[key] = env[key]; | |
}); | |
/** | |
* The currently active debug mode names, and names to skip. | |
*/ | |
createDebug.names = []; | |
createDebug.skips = []; | |
/** | |
* Map of special "%n" handling functions, for the debug "format" argument. | |
* | |
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". | |
*/ | |
createDebug.formatters = {}; | |
/** | |
* Selects a color for a debug namespace | |
* @param {String} namespace The namespace string for the debug instance to be colored | |
* @return {Number|String} An ANSI color code for the given namespace | |
* @api private | |
*/ | |
function selectColor(namespace) { | |
let hash = 0; | |
for (let i = 0; i < namespace.length; i++) { | |
hash = ((hash << 5) - hash) + namespace.charCodeAt(i); | |
hash |= 0; // Convert to 32bit integer | |
} | |
return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; | |
} | |
createDebug.selectColor = selectColor; | |
/** | |
* Create a debugger with the given `namespace`. | |
* | |
* @param {String} namespace | |
* @return {Function} | |
* @api public | |
*/ | |
function createDebug(namespace) { | |
let prevTime; | |
let enableOverride = null; | |
let namespacesCache; | |
let enabledCache; | |
function debug(...args) { | |
// Disabled? | |
if (!debug.enabled) { | |
return; | |
} | |
const self = debug; | |
// Set `diff` timestamp | |
const curr = Number(new Date()); | |
const ms = curr - (prevTime || curr); | |
self.diff = ms; | |
self.prev = prevTime; | |
self.curr = curr; | |
prevTime = curr; | |
args[0] = createDebug.coerce(args[0]); | |
if (typeof args[0] !== 'string') { | |
// Anything else let's inspect with %O | |
args.unshift('%O'); | |
} | |
// Apply any `formatters` transformations | |
let index = 0; | |
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { | |
// If we encounter an escaped % then don't increase the array index | |
if (match === '%%') { | |
return '%'; | |
} | |
index++; | |
const formatter = createDebug.formatters[format]; | |
if (typeof formatter === 'function') { | |
const val = args[index]; | |
match = formatter.call(self, val); | |
// Now we need to remove `args[index]` since it's inlined in the `format` | |
args.splice(index, 1); | |
index--; | |
} | |
return match; | |
}); | |
// Apply env-specific formatting (colors, etc.) | |
createDebug.formatArgs.call(self, args); | |
const logFn = self.log || createDebug.log; | |
logFn.apply(self, args); | |
} | |
debug.namespace = namespace; | |
debug.useColors = createDebug.useColors(); | |
debug.color = createDebug.selectColor(namespace); | |
debug.extend = extend; | |
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. | |
Object.defineProperty(debug, 'enabled', { | |
enumerable: true, | |
configurable: false, | |
get: () => { | |
if (enableOverride !== null) { | |
return enableOverride; | |
} | |
if (namespacesCache !== createDebug.namespaces) { | |
namespacesCache = createDebug.namespaces; | |
enabledCache = createDebug.enabled(namespace); | |
} | |
return enabledCache; | |
}, | |
set: v => { | |
enableOverride = v; | |
} | |
}); | |
// Env-specific initialization logic for debug instances | |
if (typeof createDebug.init === 'function') { | |
createDebug.init(debug); | |
} | |
return debug; | |
} | |
function extend(namespace, delimiter) { | |
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); | |
newDebug.log = this.log; | |
return newDebug; | |
} | |
/** | |
* Enables a debug mode by namespaces. This can include modes | |
* separated by a colon and wildcards. | |
* | |
* @param {String} namespaces | |
* @api public | |
*/ | |
function enable(namespaces) { | |
createDebug.save(namespaces); | |
createDebug.namespaces = namespaces; | |
createDebug.names = []; | |
createDebug.skips = []; | |
const split = (typeof namespaces === 'string' ? namespaces : '') | |
.trim() | |
.replace(/\s+/g, ',') | |
.split(',') | |
.filter(Boolean); | |
for (const ns of split) { | |
if (ns[0] === '-') { | |
createDebug.skips.push(ns.slice(1)); | |
} else { | |
createDebug.names.push(ns); | |
} | |
} | |
} | |
/** | |
* Checks if the given string matches a namespace template, honoring | |
* asterisks as wildcards. | |
* | |
* @param {String} search | |
* @param {String} template | |
* @return {Boolean} | |
*/ | |
function matchesTemplate(search, template) { | |
let searchIndex = 0; | |
let templateIndex = 0; | |
let starIndex = -1; | |
let matchIndex = 0; | |
while (searchIndex < search.length) { | |
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) { | |
// Match character or proceed with wildcard | |
if (template[templateIndex] === '*') { | |
starIndex = templateIndex; | |
matchIndex = searchIndex; | |
templateIndex++; // Skip the '*' | |
} else { | |
searchIndex++; | |
templateIndex++; | |
} | |
} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition | |
// Backtrack to the last '*' and try to match more characters | |
templateIndex = starIndex + 1; | |
matchIndex++; | |
searchIndex = matchIndex; | |
} else { | |
return false; // No match | |
} | |
} | |
// Handle trailing '*' in template | |
while (templateIndex < template.length && template[templateIndex] === '*') { | |
templateIndex++; | |
} | |
return templateIndex === template.length; | |
} | |
/** | |
* Disable debug output. | |
* | |
* @return {String} namespaces | |
* @api public | |
*/ | |
function disable() { | |
const namespaces = [ | |
...createDebug.names, | |
...createDebug.skips.map(namespace => '-' + namespace) | |
].join(','); | |
createDebug.enable(''); | |
return namespaces; | |
} | |
/** | |
* Returns true if the given mode name is enabled, false otherwise. | |
* | |
* @param {String} name | |
* @return {Boolean} | |
* @api public | |
*/ | |
function enabled(name) { | |
for (const skip of createDebug.skips) { | |
if (matchesTemplate(name, skip)) { | |
return false; | |
} | |
} | |
for (const ns of createDebug.names) { | |
if (matchesTemplate(name, ns)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Coerce `val`. | |
* | |
* @param {Mixed} val | |
* @return {Mixed} | |
* @api private | |
*/ | |
function coerce(val) { | |
if (val instanceof Error) { | |
return val.stack || val.message; | |
} | |
return val; | |
} | |
/** | |
* XXX DO NOT USE. This is a temporary stub function. | |
* XXX It WILL be removed in the next major release. | |
*/ | |
function destroy() { | |
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); | |
} | |
createDebug.enable(createDebug.load()); | |
return createDebug; | |
} | |
module.exports = setup; | |