package/package.json000644 0000001753 3560116604 011554 0ustar00000000 000000 { "name": "webpack-log", "version": "2.0.0", "description": "A common logger for the webpack ecosystem", "main": "src/index.js", "files": [ "src" ], "engines": { "node": ">= 6" }, "scripts": { "lint": "eslint src test", "test": "nyc --reporter lcovonly mocha --full-trace --check-leaks", "release": "standard-version" }, "dependencies": { "ansi-colors": "^3.0.0", "uuid": "^3.3.2" }, "devDependencies": { "assert": "^1.4.1", "eslint": "^5.4.0", "eslint-config-webpack": "^1.2.5", "eslint-plugin-import": "^2.14.0", "mocha": "^5.2.0", "nyc": "^12.0.2", "sinon": "^6.1.5", "standard-version": "^4.4.0", "strip-ansi": "^4.0.0" }, "author": "Andrew Powell ", "issues": "https://github.com/webpack-contrib/webpack-log/issues", "homepage": "https://github.com/webpack-contrib/webpack-log#readme", "repository": "https://github.com/webpack-contrib/webpack-log.git", "license": "MIT" } package/CHANGELOG.md000644 0000001175 3560116604 011075 0ustar00000000 000000 # Change Log All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. # [2.0.0](https://github.com/webpack-contrib/webpack-log/compare/v1.2.0...v2.0.0) (2018-08-23) ### Code Refactoring * **package:** replace `chalk` with `ansi-colors` (`dependencies`) ([#4](https://github.com/webpack-contrib/webpack-log/issues/4)) ([5b793d4](https://github.com/webpack-contrib/webpack-log/commit/5b793d4)) ### BREAKING CHANGES * **package:** `module.exports.chalk` was renamed to `module.exports.colors` package/LICENSE000644 0000002060 3560116604 010263 0ustar00000000 000000 MIT License Copyright (c) 2017 webpack-contrib Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/README.md000644 0000006500 3560116604 010540 0ustar00000000 000000
[![npm][npm]][npm-url] [![node][node]][node-url] [![deps][deps]][deps-url] [![tests][tests]][tests-url] [![coverage][cover]][cover-url] [![chat][chat]][chat-url] # webpack-log A common logging module for the Webpack ecosystem. `webpack-log` leverages [`loglevelnext`][loglevelnext]. ## Getting Started First thing's first, install the module: ```console npm install webpack-log --save ``` _Note: We do not recommend installing this module globally._ ## Requirements `webpack-log` requires Node v6 or higher. ## Usage ```js const weblog = require('webpack-log'); const log = weblog({ name: 'wds' }) // webpack-dev-server log.info('Server Starting'); ``` The code above will produce: ![output](output.png) ## Options The default export (`function`) will return a logger, given an `options` Object. The following is a property reference for the Object. _Note: the logger returned is unique by default, due to the nature of the `webpack` ecosystem. Please reference the [`unique`](#unique) option below for disabling this feature and to force caching._ ### level Type: `String` Default: `'info'` Specifies the level the logger should use. A logger will not produce output for any log level _beneath_ the specified level. Available levels and order are: ```js [ 'trace', 'debug', 'info', 'warn', 'error', 'silent' ] ``` _Note: The level names shown above correspond to the available logging methods, with the notable exception of the `silent` level._ ### name _Required_ Type: `String` Default: `''` Specifies the name of the log to create. This property is required, and used to differentiate between loggers when `webpack-log` is used in multiple projects executing in the same process space. ### timestamp Type: `Boolean` Default: `false` If `true`, instructs the logger to display a timestamp for log output, preceding all other data. ### unique Type: `Boolean` Default: `true` If `false`, instructs the logger to used cached versions of a log with the same name. Due to the nature of the `webpack` ecosystem and multiple plugin/loader use in the same process space, loggers are created as unique instances by default. By passing `false` for this property, the module is instructed to cache the requested logger. ## Contributing We welcome your contributions! Please have a read of [CONTRIBUTING.md](CONTRIBUTING.md) for more information on how to get involved. ## License #### [MIT](./LICENSE) [npm]: https://img.shields.io/npm/v/webpack-log.svg [npm-url]: https://npmjs.com/package/webpack-log [node]: https://img.shields.io/node/v/webpack-log.svg [node-url]: https://nodejs.org [deps]: https://david-dm.org/webpack-contrib/webpack-log.svg [deps-url]: https://david-dm.org/webpack-contrib/webpack-log [tests]: http://img.shields.io/travis/webpack-contrib/webpack-log.svg [tests-url]: https://travis-ci.org/webpack-contrib/webpack-log [cover]: https://codecov.io/gh/webpack-contrib/webpack-log/branch/master/graph/badge.svg [cover-url]: https://codecov.io/gh/webpack-contrib/webpack-log [chat]: https://badges.gitter.im/webpack/webpack.svg [chat-url]: https://gitter.im/webpack/webpack [loglevelnext]: https://github.com/shellscape/loglevelnext package/src/index.js000644 0000003525 3560116604 011521 0ustar00000000 000000 'use strict'; /* global window: true */ /* eslint-disable no-shadow, no-param-reassign, space-before-function-paren */ const uuid = require('uuid/v4'); const colors = require('ansi-colors'); const loglevel = require('./loglevel'); const symbols = { trace: colors.grey('₸'), debug: colors.cyan('➤'), info: colors.blue(colors.symbols.info), warn: colors.yellow(colors.symbols.warning), error: colors.red(colors.symbols.cross) }; const defaults = { name: '', level: 'info', unique: true }; const prefix = { level (options) { return symbols[options.level]; }, template: `{{level}} ${colors.gray('「{{name}}」')}: ` }; function log (options) { const opts = Object.assign({}, defaults, options); const { id } = options; opts.prefix = Object.assign({}, prefix, options.prefix); delete opts.id; Object.defineProperty(opts, 'id', { get() { if (!id) { return this.name + (opts.unique ? `-${uuid()}` : ''); } return id; } }); if (opts.timestamp) { opts.prefix.template = `[{{time}}] ${opts.prefix.template}`; } const log = loglevel.getLogger(opts); if (!Object.prototype.hasOwnProperty.call(log, 'id')) { Object.defineProperty(log, 'id', { get() { return opts.id; } }); } return log; } module.exports = log; // NOTE: this is exported so that consumers of webpack-log can use the same // version of ansi-colors to decorate log messages without incurring additional // dependency overhead module.exports.colors = colors; // NOTE: This is an undocumented function solely for the purpose of tests. // Do not use this method in production code. Using in production code // may result in strange behavior. module.exports.delLogger = function delLogger(name) { delete loglevel.loggers[name]; }; module.exports.factories = loglevel.factories; package/src/loglevel/index.js000644 0000002632 3560116604 013330 0ustar00000000 000000 'use strict'; /* global window: true */ /* eslint-disable no-shadow, no-param-reassign, space-before-function-paren */ const LogLevel = require('./LogLevel'); const MethodFactory = require('./MethodFactory'); const PrefixFactory = require('./PrefixFactory'); const defaultLogger = new LogLevel({ name: 'default' }); const cache = { default: defaultLogger }; // Grab the current global log variable in case of overwrite const existing = (typeof window !== 'undefined') ? window.log : null; const loglevel = Object.assign(defaultLogger, { get factories() { return { MethodFactory, PrefixFactory }; }, get loggers() { return cache; }, getLogger(options) { if (typeof options === 'string') { options = { name: options }; } if (!options.id) { options.id = options.name; } const { name, id } = options; const defaults = { level: defaultLogger.level }; if (typeof name !== 'string' || !name || !name.length) { throw new TypeError('You must supply a name when creating a logger'); } let logger = cache[id]; if (!logger) { logger = new LogLevel(Object.assign({}, defaults, options)); cache[id] = logger; } return logger; }, noConflict() { if (typeof window !== 'undefined' && window.log === defaultLogger) { window.log = existing; } return defaultLogger; } }); module.exports = loglevel; package/src/loglevel/LogLevel.js000644 0000004014 3560116604 013726 0ustar00000000 000000 'use strict'; /* global window: true */ /* eslint-disable multiline-ternary, no-param-reassign */ const PrefixFactory = require('./PrefixFactory'); const MethodFactory = require('./MethodFactory'); const defaults = { name: +new Date(), level: 'warn', prefix: null, factory: null }; class LogLevel { constructor(options) { // implement for some _very_ loose type checking. avoids getting into a // circular require between MethodFactory and LogLevel this.type = 'LogLevel'; this.options = Object.assign({}, defaults, options); this.methodFactory = options.factory; if (!this.methodFactory) { const factory = options.prefix ? new PrefixFactory(this, options.prefix) : new MethodFactory(this); this.methodFactory = factory; } if (!this.methodFactory.logger) { this.methodFactory.logger = this; } this.name = options.name || ''; // this.level is a setter, do this after setting up the factory this.level = this.options.level; } get factory() { return this.methodFactory; } set factory(factory) { factory.logger = this; this.methodFactory = factory; this.methodFactory.replaceMethods(this.level); } enable() { this.level = this.levels.TRACE; } disable() { this.level = this.levels.SILENT; } get level() { return this.currentLevel; } set level(logLevel) { const level = this.methodFactory.distillLevel(logLevel); if (level == null) { throw new Error( `loglevel: setLevel() called with invalid level: ${logLevel}` ); } this.currentLevel = level; this.methodFactory.replaceMethods(level); if (typeof console === 'undefined' && level < this.levels.SILENT) { // eslint-disable-next-line no-console console.warn( 'loglevel: console is undefined. The log will produce no output' ); } } get levels() { // eslint-disable-line class-methods-use-this return this.methodFactory.levels; } } module.exports = LogLevel; package/src/loglevel/MethodFactory.js000644 0000006033 3560116604 014770 0ustar00000000 000000 'use strict'; /* eslint-disable arrow-parens, multiline-ternary, consistent-return, no-param-reassign, prefer-destructuring */ const noop = () => {}; const levels = Symbol('levels'); const instance = Symbol('instance'); class MethodFactory { constructor(logger) { this[levels] = { TRACE: 0, DEBUG: 1, INFO: 2, WARN: 3, ERROR: 4, SILENT: 5 }; this[instance] = logger; } set logger(logger) { this[instance] = logger; } get logger() { return this[instance]; } get levels() { return this[levels]; } get methods() { return Object.keys(this.levels) .map((key) => key.toLowerCase()) .filter((key) => key !== 'silent'); } distillLevel(level) { let result = level; if ( typeof result === 'string' && typeof this.levels[result.toUpperCase()] !== 'undefined' ) { result = this.levels[result.toUpperCase()]; } if (this.levelValid(result)) { return result; } } levelValid(level) { if ( typeof level === 'number' && level >= 0 && level <= this.levels.SILENT ) { return true; } return false; } /** * Build the best logging method possible for this env * Wherever possible we want to bind, not wrap, to preserve stack traces. * Since we're targeting modern browsers, there's no need to wait for the * console to become available. */ // eslint-disable-next-line class-methods-use-this make(method) { if (method === 'debug') { method = 'log'; } /* eslint-disable no-console */ if (typeof console[method] !== 'undefined') { return this.bindMethod(console, method); } else if (typeof console.log !== 'undefined') { return this.bindMethod(console, 'log'); } /* eslint-enable no-console */ return noop; } // eslint-disable-next-line class-methods-use-this bindMethod(obj, name) { const method = obj[name]; if (typeof method.bind === 'function') { return method.bind(obj); } try { return Function.prototype.bind.call(method, obj); } catch (err) { // Missing bind shim or IE8 + Modernizr, fallback to wrapping return function result() { // eslint-disable-next-line prefer-rest-params return Function.prototype.apply.apply(method, [obj, arguments]); }; } } replaceMethods(logLevel) { const level = this.distillLevel(logLevel); if (level == null) { throw new Error( `loglevel: replaceMethods() called with invalid level: ${logLevel}` ); } if (!this.logger || this.logger.type !== 'LogLevel') { throw new TypeError( 'loglevel: Logger is undefined or invalid. Please specify a valid Logger instance.' ); } this.methods.forEach((method) => { this.logger[method] = (this.levels[method.toUpperCase()] < level) ? noop : this.make(method); }); // Define log.log as an alias for log.debug this.logger.log = this.logger.debug; } } module.exports = MethodFactory; package/src/loglevel/PrefixFactory.js000644 0000002156 3560116604 015007 0ustar00000000 000000 'use strict'; /* eslint-disable no-param-reassign, space-before-function-paren */ const MethodFactory = require('./MethodFactory'); const defaults = { name (options) { return options.logger.name; }, time () { return new Date().toTimeString().split(' ')[0]; }, level (options) { return `[${options.level}]`; }, template: '{{time}} {{level}} ' }; class PrefixFactory extends MethodFactory { constructor(logger, options) { super(logger); this.options = Object.assign({}, defaults, options); } interpolate(level) { return this.options.template.replace(/{{([^{}]*)}}/g, (stache, prop) => { const fn = this.options[prop]; if (fn) { return fn({ level, logger: this.logger }); } return stache; }); } make(method) { const og = super.make(method); return (...args) => { const [first] = args; const output = this.interpolate(method); if (typeof first === 'string') { args[0] = output + first; } else { args.unshift(output); } og(...args); }; } } module.exports = PrefixFactory;