diff --git a/README.md b/README.md index 3b168838..7a8fd443 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](https://www.npmjs.com/package/debug): + +```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... 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..f3fa86da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "debug", - "version": "4.3.2", + "version": "5.0.0-canary.0", "repository": { "type": "git", "url": "git://github.com/visionmedia/debug.git" @@ -27,33 +27,45 @@ "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 } }, + "type": "module", "main": "./src/index.js", - "browser": "./src/browser.js", + "exports": { + ".": { + "import": { + "browser": "./src/browser.js", + "default": "./src/index.js" + } + }, + "./package.json": "./package.json" + }, "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..642ac45b 100644 --- a/src/browser.js +++ b/src/browser.js @@ -3,28 +3,15 @@ /** * This is the web browser implementation of `debug()`. */ +import humanize from 'ms'; +import setup from './common.js'; -exports.formatArgs = formatArgs; -exports.save = save; -exports.load = load; -exports.useColors = useColors; -exports.storage = localstorage(); -exports.destroy = (() => { - let warned = false; - - 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`.'); - } - }; -})(); +const storage = localstorage(); /** * Colors. */ - -exports.colors = [ +const colors = [ '#0000CC', '#0000FF', '#0033CC', @@ -100,7 +87,7 @@ exports.colors = [ '#FF9900', '#FF9933', '#FFCC00', - '#FFCC33' + '#FFCC33', ]; /** @@ -142,14 +129,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 +172,7 @@ function formatArgs(args) { * * @api public */ -exports.log = console.debug || console.log || (() => {}); +const log = console.debug || console.log || (() => { }); /** * Save `namespaces`. @@ -197,9 +183,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 +202,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 +226,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 +237,17 @@ function localstorage() { } } -module.exports = require('./common')(exports); - -const {formatters} = module.exports; - -/** - * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. - */ +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; + } + }; +} -formatters.j = function (v) { - try { - return JSON.stringify(v); - } catch (error) { - return '[UnexpectedJSONParseError]: ' + error.message; - } -}; +export default setup({ formatArgs, save, load, useColors, setupFormatters, colors, storage, log }); diff --git a/src/common.js b/src/common.js index 6d571d28..19c92223 100644 --- a/src/common.js +++ b/src/common.js @@ -1,17 +1,17 @@ - /** * This is the common logic for both the Node.js and web browser * implementations of `debug()`. */ +import humanize from 'ms'; -function setup(env) { +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 = require('ms'); + createDebug.humanize = humanize; createDebug.destroy = destroy; Object.keys(env).forEach(key => { @@ -266,9 +266,9 @@ function setup(env) { 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; } - -module.exports = setup; diff --git a/src/index.js b/src/index.js index bf4c57f2..42b4c8da 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,14 @@ -/** - * Detect Electron renderer / nwjs process, which is node, but we should - * treat as a browser. - */ +import createDebugNode from './node.js'; +import createDebugBrowser from './browser.js'; -if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { - module.exports = require('./browser.js'); -} else { - module.exports = require('./node.js'); +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; } + +const createDebug = isBrowser ? createDebugBrowser : createDebugNode; + +export default createDebug; diff --git a/src/node.js b/src/node.js index 79bc085c..26b3651e 100644 --- a/src/node.js +++ b/src/node.js @@ -2,29 +2,20 @@ * Module dependencies. */ -const tty = require('tty'); -const util = require('util'); +import tty from 'tty'; +import util from 'util'; +import humanize from 'ms'; +import setup from './common.js'; /** * 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`.' -); - /** * Colors. */ -exports.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) @@ -32,7 +23,7 @@ try { const supportsColor = require('supports-color'); if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { - exports.colors = [ + colors = [ 20, 21, 26, @@ -108,7 +99,7 @@ try { 214, 215, 220, - 221 + 221, ]; } } catch (error) { @@ -121,7 +112,7 @@ try { * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js */ -exports.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 @@ -153,9 +144,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 +156,9 @@ function useColors() { */ function formatArgs(args) { - const {namespace: name, useColors} = this; + const { + namespace: name, useColors + } = this; if (useColors) { const c = this.color; @@ -173,14 +166,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 +224,31 @@ 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. - */ +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); + }; +} -formatters.O = function (v) { - this.inspectOpts.colors = this.useColors; - return util.inspect(v, this.inspectOpts); -}; +export default setup({ init, log, formatArgs, save, load, useColors, setupFormatters, colors, 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', () => {