Ejdjdososs/fable-ai
0
1 2/**3 * This is the common logic for both the Node.js and web browser4 * implementations of `debug()`.5 */6 7function 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 namespace37 * @param {String} namespace The namespace string for the debug instance to be colored38 * @return {Number|String} An ANSI color code for the given namespace39 * @api private40 */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 integer47 }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} namespace57 * @return {Function}58 * @api public59 */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` timestamp75 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 %O86 args.unshift('%O');87 }88 89 // Apply any `formatters` transformations90 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 index93 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 instances142 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 modes157 * separated by a colon and wildcards.158 *159 * @param {String} namespaces160 * @api public161 */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, honoring186 * asterisks as wildcards.187 *188 * @param {String} search189 * @param {String} template190 * @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 wildcard201 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-condition210 // Backtrack to the last '*' and try to match more characters211 templateIndex = starIndex + 1;212 matchIndex++;213 searchIndex = matchIndex;214 } else {215 return false; // No match216 }217 }218 219 // Handle trailing '*' in template220 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} namespaces231 * @api public232 */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} name246 * @return {Boolean}247 * @api public248 */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} val269 * @return {Mixed}270 * @api private271 */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 292module.exports = setup;293 