draft: refactor project so it sits on top of a standalone app
This commit is contained in:
+16
@@ -0,0 +1,16 @@
|
||||
# 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.
|
||||
|
||||
<a name="2.0.0"></a>
|
||||
# [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`
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
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.
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<div align="center">
|
||||
<a href="https://github.com/webpack/webpack">
|
||||
<img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
[![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:
|
||||
|
||||

|
||||
|
||||
## 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: `'<unknown>'`
|
||||
|
||||
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
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"_from": "webpack-log@^2.0.0",
|
||||
"_id": "webpack-log@2.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
|
||||
"_location": "/webpack-log",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "webpack-log@^2.0.0",
|
||||
"name": "webpack-log",
|
||||
"escapedName": "webpack-log",
|
||||
"rawSpec": "^2.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^2.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/webpack-dev-middleware",
|
||||
"/webpack-dev-server"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
|
||||
"_shasum": "5b7928e0637593f119d32f6227c1e0ac31e1b47f",
|
||||
"_spec": "webpack-log@^2.0.0",
|
||||
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-dev-server",
|
||||
"author": {
|
||||
"name": "Andrew Powell",
|
||||
"email": "andrew@shellscape.org"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/webpack-contrib/webpack-log/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"ansi-colors": "^3.0.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "A common logger for the webpack ecosystem",
|
||||
"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"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"homepage": "https://github.com/webpack-contrib/webpack-log#readme",
|
||||
"issues": "https://github.com/webpack-contrib/webpack-log/issues",
|
||||
"license": "MIT",
|
||||
"main": "src/index.js",
|
||||
"name": "webpack-log",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/webpack-contrib/webpack-log.git"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint src test",
|
||||
"release": "standard-version",
|
||||
"test": "nyc --reporter lcovonly mocha --full-trace --check-leaks"
|
||||
},
|
||||
"version": "2.0.0"
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
'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: '<unknown>',
|
||||
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;
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
'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 || '<unknown>';
|
||||
// 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;
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
'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;
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
'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;
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
'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;
|
||||
Reference in New Issue
Block a user