From 58040d0cd08f55ad3e7d2dca27a20a4d68b53f05 Mon Sep 17 00:00:00 2001 From: konakona Date: Mon, 11 Oct 2021 23:31:14 +0300 Subject: [PATCH 1/5] Use ESModules instead of module.exports #786 --- karma.conf.js => karma.conf.cjs | 20 +-- package.json | 34 ++-- src/browser.js | 63 +++----- src/common.js | 274 -------------------------------- src/index.js | 269 ++++++++++++++++++++++++++++++- src/node.js | 88 +++++----- test.js | 4 +- 7 files changed, 359 insertions(+), 393 deletions(-) rename karma.conf.js => karma.conf.cjs (86%) delete mode 100644 src/common.js diff --git a/karma.conf.js b/karma.conf.cjs similarity index 86% rename from karma.conf.js rename to karma.conf.cjs index 6e835858..8c45cfdb 100644 --- a/karma.conf.js +++ b/karma.conf.cjs @@ -6,9 +6,9 @@ module.exports = function (config) { // List of files / patterns to load in the browser files: [ - 'src/browser.js', - 'src/common.js', - 'test.js' + { + pattern: 'test.js', type: 'module', + }, ], // Test results reporter to use @@ -32,26 +32,28 @@ module.exports = function (config) { customLaunchers: { HeadlessChrome: { base: 'ChromeHeadless', - flags: ['--no-sandbox'] - } + flags: ['--no-sandbox'], + }, }, preprocessors: { // *Sigh* what a glob, folks! - '{{!(node_modules),*.js},!(node_modules)/**/*.js}': ['browserify'] + '{{!(node_modules),*.js},!(node_modules)/**/*.js}': ['browserify'], }, browserify: { debug: true, - transform: ['brfs'] + transform: [['babelify', { + presets: ['@babel/preset-env'], + }]], }, // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits - singleRun: true, + singleRun: false, // Concurrency level // how many browser should be started simultaneous - concurrency: 1 + concurrency: 1, }); }; diff --git a/package.json b/package.json index b7d70acb..30766afb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "debug", - "version": "4.3.2", + "version": "5.0.0-canary.0", + "type": "module", "repository": { "type": "git", "url": "git://github.com/visionmedia/debug.git" @@ -27,33 +28,36 @@ "lint": "xo", "test": "npm run test:node && npm run test:browser && npm run lint", "test:node": "istanbul cover _mocha -- test.js", - "test:browser": "karma start --single-run", + "test:browser": "karma start karma.conf.cjs --single-run", + "debug:test:browser": "karma start karma.conf.cjs", "test:coverage": "cat ./coverage/lcov.info | coveralls" }, "dependencies": { - "ms": "2.1.2" + "ms": "3.0.0-canary.1" }, "devDependencies": { - "brfs": "^2.0.1", - "browserify": "^16.2.3", - "coveralls": "^3.0.2", + "@babel/core": "^7.15.8", + "@babel/preset-env": "^7.15.8", + "babelify": "^10.0.0", + "browserify": "^17.0.0", + "coveralls": "^3.1.1", "istanbul": "^0.4.5", - "karma": "^3.1.4", - "karma-browserify": "^6.0.0", - "karma-chrome-launcher": "^2.2.0", - "karma-mocha": "^1.3.0", - "mocha": "^5.2.0", - "mocha-lcov-reporter": "^1.2.0", - "xo": "^0.23.0" + "karma": "^6.3.4", + "karma-browserify": "^8.1.0", + "karma-chrome-launcher": "^3.1.0", + "karma-mocha": "^2.0.1", + "mocha": "^9.1.2", + "mocha-lcov-reporter": "^1.3.0", + "xo": "^0.45.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } }, - "main": "./src/index.js", + "exports": "./src/index.js", "browser": "./src/browser.js", "engines": { - "node": ">=6.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } } diff --git a/src/browser.js b/src/browser.js index cd0fc35d..9d34c363 100644 --- a/src/browser.js +++ b/src/browser.js @@ -3,28 +3,18 @@ /** * This is the web browser implementation of `debug()`. */ +import humanize from 'ms'; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = localstorage(); -exports.destroy = (() => { - let warned = false; +export { + formatArgs, save, load, useColors, setupFormatters, +}; - return () => { - if (!warned) { - warned = true; - console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); - } - }; -})(); +export const storage = localstorage(); /** * Colors. */ - -exports.colors = [ +export const colors = [ '#0000CC', '#0000FF', '#0033CC', @@ -100,7 +90,7 @@ exports.colors = [ '#FF9900', '#FF9933', '#FFCC00', - '#FFCC33' + '#FFCC33', ]; /** @@ -142,14 +132,13 @@ function useColors() { * * @api public */ - function formatArgs(args) { args[0] = (this.useColors ? '%c' : '') + this.namespace + (this.useColors ? ' %c' : ' ') + args[0] + (this.useColors ? '%c ' : ' ') + - '+' + module.exports.humanize(this.diff); + '+' + humanize(this.diff); if (!this.useColors) { return; @@ -186,7 +175,7 @@ function formatArgs(args) { * * @api public */ -exports.log = console.debug || console.log || (() => {}); +export const log = console.debug || console.log || (() => { }); /** * Save `namespaces`. @@ -197,9 +186,9 @@ exports.log = console.debug || console.log || (() => {}); function save(namespaces) { try { if (namespaces) { - exports.storage.setItem('debug', namespaces); + storage.setItem('debug', namespaces); } else { - exports.storage.removeItem('debug'); + storage.removeItem('debug'); } } catch (error) { // Swallow @@ -216,7 +205,7 @@ function save(namespaces) { function load() { let r; try { - r = exports.storage.getItem('debug'); + r = storage.getItem('debug'); } catch (error) { // Swallow // XXX (@Qix-) should we be logging these? @@ -240,7 +229,6 @@ function load() { * @return {LocalStorage} * @api private */ - function localstorage() { try { // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context @@ -252,18 +240,15 @@ function localstorage() { } } -module.exports = require('./common')(exports); - -const {formatters} = module.exports; - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ - -formatters.j = function (v) { - try { - return JSON.stringify(v); - } catch (error) { - return '[UnexpectedJSONParseError]: ' + error.message; - } -}; +function setupFormatters(formatters) { + /** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } + }; +} diff --git a/src/common.js b/src/common.js deleted file mode 100644 index 6d571d28..00000000 --- a/src/common.js +++ /dev/null @@ -1,274 +0,0 @@ - -/** - * 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 = []; - - let i; - const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - const len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) { - // ignore empty strings - continue; - } - - namespaces = split[i].replace(/\*/g, '.*?'); - - if (namespaces[0] === '-') { - createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - createDebug.names.push(new RegExp('^' + namespaces + '$')); - } - } - } - - /** - * Disable debug output. - * - * @return {String} namespaces - * @api public - */ - function disable() { - const namespaces = [ - ...createDebug.names.map(toNamespace), - ...createDebug.skips.map(toNamespace).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) { - if (name[name.length - 1] === '*') { - return true; - } - - let i; - let len; - - for (i = 0, len = createDebug.skips.length; i < len; i++) { - if (createDebug.skips[i].test(name)) { - return false; - } - } - - for (i = 0, len = createDebug.names.length; i < len; i++) { - if (createDebug.names[i].test(name)) { - return true; - } - } - - return false; - } - - /** - * Convert regexp to namespace - * - * @param {RegExp} regxep - * @return {String} namespace - * @api private - */ - function toNamespace(regexp) { - return regexp.toString() - .substring(2, regexp.toString().length - 2) - .replace(/\.\*\?$/, '*'); - } - - /** - * 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; diff --git a/src/index.js b/src/index.js index bf4c57f2..fb2dc461 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,267 @@ +import humanize from 'ms'; + +import * as nodeDebug from './node.js'; +import * as browserDebug from './browser.js'; + + +const backend = (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) ? browserDebug : nodeDebug; + +const { + init, log, formatArgs, save, load, useColors, setupFormatters, colors, +} = backend; + +export default createDebug; + /** - * Detect Electron renderer / nwjs process, which is node, but we should - * treat as a browser. + * The currently active debug mode names, and names to skip. */ -if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { - module.exports = require('./browser.js'); -} else { - module.exports = require('./node.js'); +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 = {}; + +createDebug.debug = createDebug; +createDebug.default = createDebug; +createDebug.coerce = coerce; +createDebug.disable = disable; +createDebug.enable = enable; +createDebug.enabled = enabled; +createDebug.humanize = humanize; + +/** +* Selects a color for a debug namespace +* @param {String} namespace The namespace string for the 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 colors[Math.abs(hash) % colors.length]; +} + +/** +* 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] = 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.) + formatArgs.call(self, args); + + const logFn = self.log || log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = useColors(); + debug.color = selectColor(namespace); + debug.extend = extend; + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== namespaces) { + namespacesCache = namespaces; + enabledCache = enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + }, + }); + + // Env-specific initialization logic for debug instances + if (typeof init === 'function') { + init(debug); + } + + return debug; } + +function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; +} + +let namespaces; + +/** +* Enables a debug mode by namespaces. This can include modes +* separated by a colon and wildcards. +* +* @param {String} namespaces +* @api public +*/ +function enable(namespaces_) { + save(namespaces_); + namespaces = namespaces_; + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } +} + +/** +* Disable debug output. +* +* @return {String} namespaces +* @api public +*/ +function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace), + ].join(','); + enable(''); + return namespaces; +} + +/** +* Returns true if the given mode name is enabled, false otherwise. +* +* @param {String} name +* @return {Boolean} +* @api public +*/ +function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; +} + +/** +* Convert regexp to namespace +* +* @param {RegExp} regxep +* @return {String} namespace +* @api private +*/ +function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); +} + +/** +* Coerce `val`. +* +* @param {Mixed} val +* @return {Mixed} +* @api private +*/ +function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + + return val; +} + +setupFormatters(createDebug.formatters); + +enable(load()); diff --git a/src/node.js b/src/node.js index 79bc085c..e0d87d51 100644 --- a/src/node.js +++ b/src/node.js @@ -2,29 +2,23 @@ * Module dependencies. */ -const tty = require('tty'); -const util = require('util'); +import tty from 'tty'; +import util from 'util'; +import humanize from 'ms'; /** * This is the Node.js implementation of `debug()`. */ -exports.init = init; -exports.log = log; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.destroy = util.deprecate( - () => {}, - 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' -); +export { + init, log, formatArgs, save, load, useColors, setupFormatters, +}; /** * Colors. */ -exports.colors = [6, 2, 3, 4, 5, 1]; +export let colors = [6, 2, 3, 4, 5, 1]; try { // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) @@ -32,7 +26,7 @@ try { const supportsColor = require('supports-color'); if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { - exports.colors = [ + colors = [ 20, 21, 26, @@ -108,7 +102,7 @@ try { 214, 215, 220, - 221 + 221, ]; } } catch (error) { @@ -121,7 +115,7 @@ try { * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js */ -exports.inspectOpts = Object.keys(process.env).filter(key => { +export const inspectOpts = Object.keys(process.env).filter(key => { return /^debug_/i.test(key); }).reduce((obj, key) => { // Camel-case @@ -153,9 +147,9 @@ exports.inspectOpts = Object.keys(process.env).filter(key => { */ function useColors() { - return 'colors' in exports.inspectOpts ? - Boolean(exports.inspectOpts.colors) : - tty.isatty(process.stderr.fd); + return 'colors' in inspectOpts + ? Boolean(inspectOpts.colors) + : tty.isatty(process.stderr.fd); } /** @@ -165,7 +159,9 @@ function useColors() { */ function formatArgs(args) { - const {namespace: name, useColors} = this; + const { + namespace: name, useColors + } = this; if (useColors) { const c = this.color; @@ -173,14 +169,14 @@ function formatArgs(args) { const prefix = ` ${colorCode};1m${name} \u001B[0m`; args[0] = prefix + args[0].split('\n').join('\n' + prefix); - args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + args.push(colorCode + 'm+' + humanize(this.diff) + '\u001B[0m'); } else { args[0] = getDate() + name + ' ' + args[0]; } } function getDate() { - if (exports.inspectOpts.hideDate) { + if (inspectOpts.hideDate) { return ''; } return new Date().toISOString() + ' '; @@ -231,33 +227,29 @@ function load() { function init(debug) { debug.inspectOpts = {}; - const keys = Object.keys(exports.inspectOpts); + const keys = Object.keys(inspectOpts); for (let i = 0; i < keys.length; i++) { - debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + debug.inspectOpts[keys[i]] = inspectOpts[keys[i]]; } } -module.exports = require('./common')(exports); - -const {formatters} = module.exports; - -/** - * Map %o to `util.inspect()`, all on a single line. - */ - -formatters.o = function (v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts) - .split('\n') - .map(str => str.trim()) - .join(' '); -}; - -/** - * Map %O to `util.inspect()`, allowing multiple lines if needed. - */ - -formatters.O = function (v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; +function setupFormatters(formatters) { + /** + * Map %o to `util.inspect()`, all on a single line. + */ + formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); + }; + + /** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); + }; +} diff --git a/test.js b/test.js index a1d6f633..db02536d 100644 --- a/test.js +++ b/test.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ -const assert = require('assert'); -const debug = require('./src'); +import assert from 'assert'; +import debug from './src/index.js'; describe('debug', () => { it('passes a basic sanity check', () => { From 86bb364699ad257548f9f36be8432c109ba2f9c7 Mon Sep 17 00:00:00 2001 From: konakona Date: Tue, 12 Oct 2021 15:40:26 +0300 Subject: [PATCH 2/5] Changeset cleanup --- package.json | 6 +- src/browser.js | 13 ++- src/common.js | 274 +++++++++++++++++++++++++++++++++++++++++++++++++ src/index.js | 273 ++---------------------------------------------- src/node.js | 15 ++- 5 files changed, 301 insertions(+), 280 deletions(-) create mode 100644 src/common.js diff --git a/package.json b/package.json index 30766afb..460704c6 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,10 @@ "optional": true } }, - "exports": "./src/index.js", - "browser": "./src/browser.js", + "exports": { + "browser": "./src/browser.js", + "default": "./src/index.js" + }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } diff --git a/src/browser.js b/src/browser.js index 9d34c363..642ac45b 100644 --- a/src/browser.js +++ b/src/browser.js @@ -4,17 +4,14 @@ * This is the web browser implementation of `debug()`. */ import humanize from 'ms'; +import setup from './common.js'; -export { - formatArgs, save, load, useColors, setupFormatters, -}; - -export const storage = localstorage(); +const storage = localstorage(); /** * Colors. */ -export const colors = [ +const colors = [ '#0000CC', '#0000FF', '#0033CC', @@ -175,7 +172,7 @@ function formatArgs(args) { * * @api public */ -export const log = console.debug || console.log || (() => { }); +const log = console.debug || console.log || (() => { }); /** * Save `namespaces`. @@ -252,3 +249,5 @@ function setupFormatters(formatters) { } }; } + +export default setup({ formatArgs, save, load, useColors, setupFormatters, colors, storage, log }); diff --git a/src/common.js b/src/common.js new file mode 100644 index 00000000..19c92223 --- /dev/null +++ b/src/common.js @@ -0,0 +1,274 @@ +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ +import humanize from 'ms'; + +export default function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = humanize; + 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 = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).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) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * 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.setupFormatters(createDebug.formatters); + + createDebug.enable(createDebug.load()); + + return createDebug; +} diff --git a/src/index.js b/src/index.js index fb2dc461..42b4c8da 100644 --- a/src/index.js +++ b/src/index.js @@ -1,267 +1,14 @@ -import humanize from 'ms'; +import createDebugNode from './node.js'; +import createDebugBrowser from './browser.js'; -import * as nodeDebug from './node.js'; -import * as browserDebug from './browser.js'; - - -const backend = (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) ? browserDebug : nodeDebug; - -const { - init, log, formatArgs, save, load, useColors, setupFormatters, colors, -} = backend; - -export default createDebug; - -/** - * 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 = {}; - -createDebug.debug = createDebug; -createDebug.default = createDebug; -createDebug.coerce = coerce; -createDebug.disable = disable; -createDebug.enable = enable; -createDebug.enabled = enabled; -createDebug.humanize = humanize; - -/** -* Selects a color for a debug namespace -* @param {String} namespace The namespace string for the 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 colors[Math.abs(hash) % colors.length]; +let isBrowser; +try { + isBrowser = (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs); +} catch (e) { + // access to `process` fails when internalized for browser + isBrowser = true; } -/** -* 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; +const createDebug = isBrowser ? createDebugBrowser : createDebugNode; - // 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] = 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.) - formatArgs.call(self, args); - - const logFn = self.log || log; - logFn.apply(self, args); - } - - debug.namespace = namespace; - debug.useColors = useColors(); - debug.color = selectColor(namespace); - debug.extend = extend; - - Object.defineProperty(debug, 'enabled', { - enumerable: true, - configurable: false, - get: () => { - if (enableOverride !== null) { - return enableOverride; - } - if (namespacesCache !== namespaces) { - namespacesCache = namespaces; - enabledCache = enabled(namespace); - } - - return enabledCache; - }, - set: v => { - enableOverride = v; - }, - }); - - // Env-specific initialization logic for debug instances - if (typeof init === 'function') { - init(debug); - } - - return debug; -} - -function extend(namespace, delimiter) { - const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); - newDebug.log = this.log; - return newDebug; -} - -let namespaces; - -/** -* Enables a debug mode by namespaces. This can include modes -* separated by a colon and wildcards. -* -* @param {String} namespaces -* @api public -*/ -function enable(namespaces_) { - save(namespaces_); - namespaces = namespaces_; - - createDebug.names = []; - createDebug.skips = []; - - let i; - const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); - const len = split.length; - - for (i = 0; i < len; i++) { - if (!split[i]) { - // ignore empty strings - continue; - } - - namespaces = split[i].replace(/\*/g, '.*?'); - - if (namespaces[0] === '-') { - createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); - } else { - createDebug.names.push(new RegExp('^' + namespaces + '$')); - } - } -} - -/** -* Disable debug output. -* -* @return {String} namespaces -* @api public -*/ -function disable() { - const namespaces = [ - ...createDebug.names.map(toNamespace), - ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace), - ].join(','); - enable(''); - return namespaces; -} - -/** -* Returns true if the given mode name is enabled, false otherwise. -* -* @param {String} name -* @return {Boolean} -* @api public -*/ -function enabled(name) { - if (name[name.length - 1] === '*') { - return true; - } - - let i; - let len; - - for (i = 0, len = createDebug.skips.length; i < len; i++) { - if (createDebug.skips[i].test(name)) { - return false; - } - } - - for (i = 0, len = createDebug.names.length; i < len; i++) { - if (createDebug.names[i].test(name)) { - return true; - } - } - - return false; -} - -/** -* Convert regexp to namespace -* -* @param {RegExp} regxep -* @return {String} namespace -* @api private -*/ -function toNamespace(regexp) { - return regexp.toString() - .substring(2, regexp.toString().length - 2) - .replace(/\.\*\?$/, '*'); -} - -/** -* Coerce `val`. -* -* @param {Mixed} val -* @return {Mixed} -* @api private -*/ -function coerce(val) { - if (val instanceof Error) { - return val.stack || val.message; - } - - return val; -} - -setupFormatters(createDebug.formatters); - -enable(load()); +export default createDebug; diff --git a/src/node.js b/src/node.js index e0d87d51..2da6c157 100644 --- a/src/node.js +++ b/src/node.js @@ -2,23 +2,20 @@ * Module dependencies. */ -import tty from 'tty'; -import util from 'util'; +import tty from 'node:tty'; +import util from 'node:util'; import humanize from 'ms'; +import setup from './common.js'; /** * This is the Node.js implementation of `debug()`. */ -export { - init, log, formatArgs, save, load, useColors, setupFormatters, -}; - /** * Colors. */ -export let colors = [6, 2, 3, 4, 5, 1]; +let colors = [6, 2, 3, 4, 5, 1]; try { // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) @@ -115,7 +112,7 @@ try { * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js */ -export const inspectOpts = Object.keys(process.env).filter(key => { +const inspectOpts = Object.keys(process.env).filter(key => { return /^debug_/i.test(key); }).reduce((obj, key) => { // Camel-case @@ -253,3 +250,5 @@ function setupFormatters(formatters) { return util.inspect(v, this.inspectOpts); }; } + +export default setup({ init, log, formatArgs, save, load, useColors, setupFormatters, colors, inspectOpts }); From 80a55f323778a3d57d1804e51fb66c15be257f34 Mon Sep 17 00:00:00 2001 From: konakona Date: Tue, 12 Oct 2021 17:53:46 +0300 Subject: [PATCH 3/5] fix imports --- package.json | 12 +++++++++--- src/node.js | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 460704c6..f3fa86da 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { "name": "debug", "version": "5.0.0-canary.0", - "type": "module", "repository": { "type": "git", "url": "git://github.com/visionmedia/debug.git" @@ -55,9 +54,16 @@ "optional": true } }, + "type": "module", + "main": "./src/index.js", "exports": { - "browser": "./src/browser.js", - "default": "./src/index.js" + ".": { + "import": { + "browser": "./src/browser.js", + "default": "./src/index.js" + } + }, + "./package.json": "./package.json" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" diff --git a/src/node.js b/src/node.js index 2da6c157..26b3651e 100644 --- a/src/node.js +++ b/src/node.js @@ -2,8 +2,8 @@ * Module dependencies. */ -import tty from 'node:tty'; -import util from 'node:util'; +import tty from 'tty'; +import util from 'util'; import humanize from 'ms'; import setup from './common.js'; From c4aaaf71e001c88d33af25823e02d6e809d8d56a Mon Sep 17 00:00:00 2001 From: konakona <90318342+Konakona-chan@users.noreply.github.com> Date: Thu, 14 Oct 2021 15:26:17 +0300 Subject: [PATCH 4/5] Update README.md for ESM --- README.md | 62 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 3b168838..1c92d629 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,13 @@ technique. Works in Node.js and web browsers. ## Installation -```bash -$ npm install debug +This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): +Node 12+ is needed to use it and it must be `import`ed instead of `require`d. + +[npm][]: + +```sh +npm install debug ``` ## Usage @@ -20,42 +25,45 @@ $ npm install debug Example [_app.js_](./examples/node/app.js): ```js -var debug = require('debug')('http') - , http = require('http') - , name = 'My App'; +import createDebug from 'debug'; +import http from 'http'; + +const debug = createDebug('http'), + name = 'My App'; // fake app debug('booting %o', name); -http.createServer(function(req, res){ - debug(req.method + ' ' + req.url); - res.end('hello\n'); -}).listen(3000, function(){ - debug('listening'); +http.createServer(function (req, res) { + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function () { + debug('listening'); }); // fake worker of some kind -require('./worker'); +import './worker.js'; ``` Example [_worker.js_](./examples/node/worker.js): ```js -var a = require('debug')('worker:a') - , b = require('debug')('worker:b'); +import createDebug from 'debug'; + +const a = createDebug('worker:a'), b = createDebug('worker:b'); function work() { - a('doing lots of uninteresting work'); - setTimeout(work, Math.random() * 1000); + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); } work(); function workb() { - b('doing some work'); - setTimeout(workb, Math.random() * 2000); + b('doing some work'); + setTimeout(workb, Math.random() * 2000); } workb(); @@ -200,7 +208,7 @@ For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like: ```js -const createDebug = require('debug') +import createDebug from 'debug' createDebug.formatters.h = (v) => { return v.toString('hex') } @@ -249,13 +257,13 @@ setInterval(function(){ Example [_stdout.js_](./examples/node/stdout.js): ```js -var debug = require('debug'); -var error = debug('app:error'); +import debug from 'debug' +const error = debug('app:error'); // by default stderr is used error('goes to stderr!'); -var log = debug('app:log'); +const log = debug('app:log'); // set this namespace to log via console.log log.log = console.log.bind(console); // don't forget to bind to console! log('goes to stdout'); @@ -271,7 +279,8 @@ log('still goes to stdout, but via console.info now'); ## Extend You can simply extend debugger ```js -const log = require('debug')('auth'); +import createDebug from 'debug' +const log = createDebug('auth'); //creates new debug instance with extended namespace const logSign = log.extend('sign'); @@ -287,7 +296,7 @@ logLogin('hello'); //auth:login hello You can also enable debug dynamically by calling the `enable()` method : ```js -let debug = require('debug'); +import debug from 'debug' console.log(1, debug.enabled('test')); @@ -313,7 +322,7 @@ Usage : Note that calling `enable()` completely overrides previously set DEBUG variable : ``` -$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))' +$ DEBUG=foo node -e "import('debug').then(({default: dbg}) => {dbg.enable('bar'); console.log(dbg.enabled('foo'));})" => false ``` @@ -326,7 +335,7 @@ temporarily without knowing what was enabled to begin with. For example: ```js -let debug = require('debug'); +import debug from 'debug' debug.enable('foo:*,-foo:bar'); let namespaces = debug.disable(); debug.enable(namespaces); @@ -341,7 +350,8 @@ After you've created a debug instance, you can determine whether or not it is enabled by checking the `enabled` property: ```javascript -const debug = require('debug')('http'); +import createDebug from 'debug' +const debug = createDebug('http'); if (debug.enabled) { // do stuff... From 8ac5889a975067fbeeba1f1888d4248ad96164ed Mon Sep 17 00:00:00 2001 From: konakona <90318342+Konakona-chan@users.noreply.github.com> Date: Thu, 14 Oct 2021 17:32:03 +0300 Subject: [PATCH 5/5] Fix link to npm --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c92d629..7a8fd443 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ technique. Works in Node.js and web browsers. This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): Node 12+ is needed to use it and it must be `import`ed instead of `require`d. -[npm][]: +[npm](https://www.npmjs.com/package/debug): ```sh npm install debug