webpack/lib/logging/createConsoleLogger.js

214 lines
5.9 KiB
JavaScript
Raw Normal View History

2019-07-19 18:31:18 +08:00
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { LogType } = require("./Logger");
/** @typedef {import("../../declarations/WebpackOptions").FilterItemTypes} FilterItemTypes */
2019-07-24 16:51:04 +08:00
/** @typedef {import("../../declarations/WebpackOptions").FilterTypes} FilterTypes */
/** @typedef {import("./Logger").LogTypeEnum} LogTypeEnum */
/** @typedef {(item: string) => boolean} FilterFunction */
/** @typedef {(value: string, type: LogTypeEnum, args?: EXPECTED_ANY[]) => void} LoggingFunction */
2019-07-19 18:31:18 +08:00
/**
2024-06-11 21:09:50 +08:00
* @typedef {object} LoggerConsole
* @property {() => void} clear
* @property {() => void} trace
2024-10-25 02:13:59 +08:00
* @property {(...args: EXPECTED_ANY[]) => void} info
* @property {(...args: EXPECTED_ANY[]) => void} log
* @property {(...args: EXPECTED_ANY[]) => void} warn
* @property {(...args: EXPECTED_ANY[]) => void} error
* @property {(...args: EXPECTED_ANY[]) => void=} debug
* @property {(...args: EXPECTED_ANY[]) => void=} group
* @property {(...args: EXPECTED_ANY[]) => void=} groupCollapsed
* @property {(...args: EXPECTED_ANY[]) => void=} groupEnd
* @property {(...args: EXPECTED_ANY[]) => void=} status
* @property {(...args: EXPECTED_ANY[]) => void=} profile
* @property {(...args: EXPECTED_ANY[]) => void=} profileEnd
* @property {(...args: EXPECTED_ANY[]) => void=} logTime
*/
2019-07-19 18:31:18 +08:00
/**
2024-06-11 21:09:50 +08:00
* @typedef {object} LoggerOptions
* @property {false|true|"none"|"error"|"warn"|"info"|"log"|"verbose"} level loglevel
* @property {FilterTypes|boolean} debug filter for debug logging
* @property {LoggerConsole} console the console to log to
2019-07-19 18:31:18 +08:00
*/
2019-07-22 04:28:46 +08:00
/**
* @param {FilterItemTypes} item an input item
2024-03-11 22:56:35 +08:00
* @returns {FilterFunction | undefined} filter function
2019-07-22 04:28:46 +08:00
*/
const filterToFunction = item => {
if (typeof item === "string") {
const regExp = new RegExp(
2024-01-13 21:28:53 +08:00
`[\\\\/]${item.replace(/[-[\]{}()*+?.\\^$|]/g, "\\$&")}([\\\\/]|$|!|\\?)`
2019-07-22 04:28:46 +08:00
);
return ident => regExp.test(ident);
}
if (item && typeof item === "object" && typeof item.test === "function") {
return ident => item.test(ident);
}
if (typeof item === "function") {
return item;
}
if (typeof item === "boolean") {
return () => item;
}
};
/**
* @enum {number}
*/
2019-07-22 04:28:46 +08:00
const LogLevel = {
2019-07-22 16:35:26 +08:00
none: 6,
2019-07-22 04:28:46 +08:00
false: 6,
error: 5,
warn: 4,
info: 3,
log: 2,
true: 2,
verbose: 1
};
/**
* @param {LoggerOptions} options options object
2024-02-21 22:55:02 +08:00
* @returns {LoggingFunction} logging function
2019-07-22 04:28:46 +08:00
*/
module.exports = ({ level = "info", debug = false, console }) => {
const debugFilters =
2024-03-11 22:56:35 +08:00
/** @type {FilterFunction[]} */
(
typeof debug === "boolean"
? [() => debug]
: /** @type {FilterItemTypes[]} */ ([])
.concat(debug)
.map(filterToFunction)
);
2019-07-22 04:28:46 +08:00
/** @type {number} */
const loglevel = LogLevel[`${level}`] || 0;
/**
* @param {string} name name of the logger
* @param {LogTypeEnum} type type of the log entry
2024-10-25 02:13:59 +08:00
* @param {EXPECTED_ANY[]=} args arguments of the log entry
2019-07-22 04:28:46 +08:00
* @returns {void}
*/
const logger = (name, type, args) => {
const labeledArgs = () => {
2019-07-22 04:28:46 +08:00
if (Array.isArray(args)) {
if (args.length > 0 && typeof args[0] === "string") {
return [`[${name}] ${args[0]}`, ...args.slice(1)];
2019-07-22 04:28:46 +08:00
}
2024-07-31 04:21:27 +08:00
return [`[${name}]`, ...args];
2019-07-19 18:31:18 +08:00
}
2024-07-31 04:21:27 +08:00
return [];
2019-07-22 04:28:46 +08:00
};
const debug = debugFilters.some(f => f(name));
switch (type) {
case LogType.debug:
if (!debug) return;
if (typeof console.debug === "function") {
console.debug(...labeledArgs());
} else {
console.log(...labeledArgs());
}
break;
case LogType.log:
if (!debug && loglevel > LogLevel.log) return;
2019-07-19 18:31:18 +08:00
console.log(...labeledArgs());
2019-07-22 04:28:46 +08:00
break;
case LogType.info:
if (!debug && loglevel > LogLevel.info) return;
console.info(...labeledArgs());
2019-07-22 04:28:46 +08:00
break;
case LogType.warn:
if (!debug && loglevel > LogLevel.warn) return;
console.warn(...labeledArgs());
2019-07-22 04:28:46 +08:00
break;
case LogType.error:
if (!debug && loglevel > LogLevel.error) return;
console.error(...labeledArgs());
2019-07-22 04:28:46 +08:00
break;
case LogType.trace:
if (!debug) return;
console.trace();
break;
case LogType.groupCollapsed:
if (!debug && loglevel > LogLevel.log) return;
if (!debug && loglevel > LogLevel.verbose) {
if (typeof console.groupCollapsed === "function") {
console.groupCollapsed(...labeledArgs());
} else {
console.log(...labeledArgs());
}
break;
}
// falls through
2019-07-22 04:28:46 +08:00
case LogType.group:
if (!debug && loglevel > LogLevel.log) return;
if (typeof console.group === "function") {
console.group(...labeledArgs());
} else {
console.log(...labeledArgs());
}
break;
case LogType.groupEnd:
if (!debug && loglevel > LogLevel.log) return;
if (typeof console.groupEnd === "function") {
console.groupEnd();
}
break;
case LogType.time: {
2019-07-22 04:28:46 +08:00
if (!debug && loglevel > LogLevel.log) return;
2024-08-07 23:22:25 +08:00
const [label, start, end] =
/** @type {[string, number, number]} */
(args);
const ms = start * 1000 + end / 1000000;
const msg = `[${name}] ${label}: ${ms} ms`;
if (typeof console.logTime === "function") {
console.logTime(msg);
} else {
console.log(msg);
}
2019-07-22 04:28:46 +08:00
break;
}
2019-07-22 04:28:46 +08:00
case LogType.profile:
if (typeof console.profile === "function") {
console.profile(...labeledArgs());
}
break;
case LogType.profileEnd:
if (typeof console.profileEnd === "function") {
console.profileEnd(...labeledArgs());
}
break;
case LogType.clear:
if (!debug && loglevel > LogLevel.log) return;
if (typeof console.clear === "function") {
console.clear();
}
break;
case LogType.status:
if (!debug && loglevel > LogLevel.info) return;
if (typeof console.status === "function") {
2024-08-07 23:22:25 +08:00
if (!args || args.length === 0) {
console.status();
} else {
console.status(...labeledArgs());
}
2024-08-07 23:22:25 +08:00
} else if (args && args.length !== 0) {
2024-07-31 04:54:55 +08:00
console.info(...labeledArgs());
}
break;
2019-07-22 04:28:46 +08:00
default:
throw new Error(`Unexpected LogType ${type}`);
}
};
return logger;
2019-07-19 18:31:18 +08:00
};