Skip to content

Commit

Permalink
improvements
Browse files Browse the repository at this point in the history
add appendOnly flag
add custom console
add custom stream
  • Loading branch information
sokra committed Apr 6, 2021
1 parent 72ba68c commit 4e11778
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 129 deletions.
14 changes: 13 additions & 1 deletion declarations/WebpackOptions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1200,9 +1200,17 @@ export interface ExternalsPresets {
*/
export interface InfrastructureLogging {
/**
* Enables/Disables colorful output.
* Only appends lines to the output. Avoids updating existing output e. g. for status messages. This option is only used when no custom console is provided.
*/
appendOnly?: boolean;
/**
* Enables/Disables colorful output. This option is only used when no custom console is provided.
*/
colors?: boolean;
/**
* Custom console used for logging.
*/
console?: Console;
/**
* Enable debug logging for specific loggers.
*/
Expand All @@ -1211,6 +1219,10 @@ export interface InfrastructureLogging {
* Log level.
*/
level?: "none" | "error" | "warn" | "info" | "log" | "verbose";
/**
* Stream used for logging output. Defaults to process.stderr. This option is only used when no custom console is provided.
*/
stream?: NodeJS.WritableStream;
}
/**
* Custom values available in the loader context.
Expand Down
12 changes: 5 additions & 7 deletions lib/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ const A = (obj, prop, factory) => {
*/
const applyWebpackOptionsBaseDefaults = options => {
F(options, "context", () => process.cwd());
applyInfrastructureLoggingDefaults(options.infrastructureLogging);
};

/**
Expand Down Expand Up @@ -235,8 +236,6 @@ const applyWebpackOptionsDefaults = options => {
getResolveLoaderDefaults({ cache }),
options.resolveLoader
);

applyInfrastructureLoggingDefaults(options.infrastructureLogging);
};

/**
Expand Down Expand Up @@ -1077,13 +1076,12 @@ const getResolveLoaderDefaults = ({ cache }) => {
* @returns {void}
*/
const applyInfrastructureLoggingDefaults = infrastructureLogging => {
const tty = process.stderr.isTTY && process.env.TERM !== "dumb";
D(infrastructureLogging, "level", "info");
D(infrastructureLogging, "debug", false);
D(
infrastructureLogging,
"colors",
process.stderr.isTTY && process.env.TERM !== "dumb"
);
D(infrastructureLogging, "colors", tty);
D(infrastructureLogging, "appendOnly", !tty);
F(infrastructureLogging, "stream", () => process.stderr);
};

exports.applyWebpackOptionsBaseDefaults = applyWebpackOptionsBaseDefaults;
Expand Down
20 changes: 19 additions & 1 deletion lib/logging/createConsoleLogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,29 @@ const { LogType } = require("./Logger");

/** @typedef {function(string): boolean} FilterFunction */

/**
* @typedef {Object} LoggerConsole
* @property {function(): void} clear
* @property {function(): void} trace
* @property {(...args: any[]) => void} info
* @property {(...args: any[]) => void} log
* @property {(...args: any[]) => void} warn
* @property {(...args: any[]) => void} error
* @property {(...args: any[]) => void=} debug
* @property {(...args: any[]) => void=} group
* @property {(...args: any[]) => void=} groupCollapsed
* @property {(...args: any[]) => void=} groupEnd
* @property {(...args: any[]) => void=} status
* @property {(...args: any[]) => void=} profile
* @property {(...args: any[]) => void=} profileEnd
* @property {(...args: any[]) => void=} logTime
*/

/**
* @typedef {Object} LoggerOptions
* @property {false|true|"none"|"error"|"warn"|"info"|"log"|"verbose"} level loglevel
* @property {FilterTypes|boolean} debug filter for debug logging
* @property {Console & { status?: Function, logTime?: Function }} console the console to log to
* @property {LoggerConsole} console the console to log to
*/

/**
Expand Down
35 changes: 18 additions & 17 deletions lib/node/NodeEnvironmentPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ const createConsoleLogger = require("../logging/createConsoleLogger");
const NodeWatchFileSystem = require("./NodeWatchFileSystem");
const nodeConsole = require("./nodeConsole");

/** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
/** @typedef {import("../Compiler")} Compiler */

class NodeEnvironmentPlugin {
/**
* @param {Object} options options
* @param {InfrastructureLogging} options.infrastructureLogging infrastructure logging options
*/
constructor(options) {
this.options = options || {};
this.options = options;
}

/**
Expand All @@ -24,22 +29,18 @@ class NodeEnvironmentPlugin {
* @returns {void}
*/
apply(compiler) {
const console = nodeConsole(
this.options.infrastructureLogging.colors !== undefined
? this.options.infrastructureLogging.colors
: process.stderr.isTTY && process.env.TERM !== "dumb"
);
delete this.options.infrastructureLogging.colors;
compiler.infrastructureLogger = createConsoleLogger(
Object.assign(
{
level: "info",
debug: false,
console
},
this.options.infrastructureLogging
)
);
const { infrastructureLogging } = this.options;
compiler.infrastructureLogger = createConsoleLogger({
level: infrastructureLogging.level || "info",
debug: infrastructureLogging.debug || false,
console:
infrastructureLogging.console ||
nodeConsole({
colors: infrastructureLogging.colors,
appendOnly: infrastructureLogging.appendOnly,
stream: infrastructureLogging.stream
})
});
compiler.inputFileSystem = new CachedInputFileSystem(fs, 60000);
const inputFileSystem = compiler.inputFileSystem;
compiler.outputFileSystem = fs;
Expand Down
139 changes: 59 additions & 80 deletions lib/node/nodeConsole.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,102 +8,81 @@
const util = require("util");
const truncateArgs = require("../logging/truncateArgs");

const tty = process.stderr.isTTY && process.env.TERM !== "dumb";
module.exports = ({ colors, appendOnly, stream }) => {
let currentStatusMessage = undefined;
let hasStatusMessage = false;
let currentIndent = "";
let currentCollapsed = 0;

let currentStatusMessage = undefined;
let hasStatusMessage = false;
let currentIndent = "";
let currentCollapsed = 0;

const indent = (colors, str, prefix, colorPrefix, colorSuffix) => {
if (str === "") return str;
prefix = currentIndent + prefix;
if (colors) {
return (
prefix +
colorPrefix +
str.replace(/\n/g, colorSuffix + "\n" + prefix + colorPrefix) +
colorSuffix
);
} else {
return prefix + str.replace(/\n/g, "\n" + prefix);
}
};
const indent = (str, prefix, colorPrefix, colorSuffix) => {
if (str === "") return str;
prefix = currentIndent + prefix;
if (colors) {
return (
prefix +
colorPrefix +
str.replace(/\n/g, colorSuffix + "\n" + prefix + colorPrefix) +
colorSuffix
);
} else {
return prefix + str.replace(/\n/g, "\n" + prefix);
}
};

const clearStatusMessage = () => {
if (hasStatusMessage) {
process.stderr.write("\x1b[2K\r");
hasStatusMessage = false;
}
};
const clearStatusMessage = () => {
if (hasStatusMessage) {
stream.write("\x1b[2K\r");
hasStatusMessage = false;
}
};

const writeStatusMessage = () => {
if (!currentStatusMessage) return;
const l = process.stderr.columns;
const args = l
? truncateArgs(currentStatusMessage, l - 1)
: currentStatusMessage;
const str = args.join(" ");
const coloredStr = `\u001b[1m${str}\u001b[39m\u001b[22m`;
process.stderr.write(`\x1b[2K\r${coloredStr}`);
hasStatusMessage = true;
};
const writeStatusMessage = () => {
if (!currentStatusMessage) return;
const l = stream.columns;
const args = l
? truncateArgs(currentStatusMessage, l - 1)
: currentStatusMessage;
const str = args.join(" ");
const coloredStr = `\u001b[1m${str}\u001b[39m\u001b[22m`;
stream.write(`\x1b[2K\r${coloredStr}`);
hasStatusMessage = true;
};

const writeColored = (colors, prefix, colorPrefix, colorSuffix) => {
return (...args) => {
if (currentCollapsed > 0) return;
clearStatusMessage();
const str = indent(
colors,
util.format(...args),
prefix,
colorPrefix,
colorSuffix
);
process.stderr.write(str + "\n");
writeStatusMessage();
const writeColored = (prefix, colorPrefix, colorSuffix) => {
return (...args) => {
if (currentCollapsed > 0) return;
clearStatusMessage();
const str = indent(
util.format(...args),
prefix,
colorPrefix,
colorSuffix
);
stream.write(str + "\n");
writeStatusMessage();
};
};
};

module.exports = colors => {
const writeGroupMessage = writeColored(
colors,
"<-> ",
"\u001b[1m\u001b[36m",
"\u001b[39m\u001b[22m"
);

const writeGroupCollapsedMessage = writeColored(
colors,
"<+> ",
"\u001b[1m\u001b[36m",
"\u001b[39m\u001b[22m"
);

return {
log: writeColored(colors, " ", "\u001b[1m", "\u001b[22m"),
debug: writeColored(colors, " ", "", ""),
trace: writeColored(colors, " ", "", ""),
info: writeColored(
colors,
"<i> ",
"\u001b[1m\u001b[32m",
"\u001b[39m\u001b[22m"
),
warn: writeColored(
colors,
"<w> ",
"\u001b[1m\u001b[33m",
"\u001b[39m\u001b[22m"
),
error: writeColored(
colors,
"<e> ",
"\u001b[1m\u001b[31m",
"\u001b[39m\u001b[22m"
),
log: writeColored(" ", "\u001b[1m", "\u001b[22m"),
debug: writeColored(" ", "", ""),
trace: writeColored(" ", "", ""),
info: writeColored("<i> ", "\u001b[1m\u001b[32m", "\u001b[39m\u001b[22m"),
warn: writeColored("<w> ", "\u001b[1m\u001b[33m", "\u001b[39m\u001b[22m"),
error: writeColored("<e> ", "\u001b[1m\u001b[31m", "\u001b[39m\u001b[22m"),
logTime: writeColored(
colors,
"<t> ",
"\u001b[1m\u001b[35m",
"\u001b[39m\u001b[22m"
Expand All @@ -130,7 +109,7 @@ module.exports = colors => {
// eslint-disable-next-line node/no-unsupported-features/node-builtins
profileEnd: console.profileEnd && (name => console.profileEnd(name)),
clear:
tty &&
!appendOnly &&
// eslint-disable-next-line node/no-unsupported-features/node-builtins
console.clear &&
(() => {
Expand All @@ -139,8 +118,9 @@ module.exports = colors => {
console.clear();
writeStatusMessage();
}),
status: tty
? (name, ...args) => {
status: appendOnly
? writeColored("<s> ", "", "")
: (name, ...args) => {
args = args.filter(Boolean);
if (name === undefined && args.length === 0) {
clearStatusMessage();
Expand All @@ -159,6 +139,5 @@ module.exports = colors => {
writeStatusMessage();
}
}
: writeColored(colors, "<s> ", "", "")
};
};
14 changes: 13 additions & 1 deletion schemas/WebpackOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1211,10 +1211,18 @@
"type": "object",
"additionalProperties": false,
"properties": {
"appendOnly": {
"description": "Only appends lines to the output. Avoids updating existing output e. g. for status messages. This option is only used when no custom console is provided.",
"type": "boolean"
},
"colors": {
"description": "Enables/Disables colorful output.",
"description": "Enables/Disables colorful output. This option is only used when no custom console is provided.",
"type": "boolean"
},
"console": {
"description": "Custom console used for logging.",
"tsType": "Console"
},
"debug": {
"description": "Enable debug logging for specific loggers.",
"anyOf": [
Expand All @@ -1230,6 +1238,10 @@
"level": {
"description": "Log level.",
"enum": ["none", "error", "warn", "info", "log", "verbose"]
},
"stream": {
"description": "Stream used for logging output. Defaults to process.stderr. This option is only used when no custom console is provided.",
"tsType": "NodeJS.WritableStream"
}
}
},
Expand Down
4 changes: 1 addition & 3 deletions test/ConfigTestCases.template.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const fs = require("graceful-fs");
const vm = require("vm");
const { URL } = require("url");
const rimraf = require("rimraf");
const webpack = require("..");
const TerserPlugin = require("terser-webpack-plugin");
const checkArrayExpectation = require("./checkArrayExpectation");
const createLazyTestEnv = require("./helpers/createLazyTestEnv");
Expand All @@ -16,8 +17,6 @@ const prepareOptions = require("./helpers/prepareOptions");
const { parseResource } = require("../lib/util/identifier");
const captureStdio = require("./helpers/captureStdio");

let webpack;

const casesPath = path.join(__dirname, "configCases");
const categories = fs.readdirSync(casesPath).map(cat => {
return {
Expand All @@ -34,7 +33,6 @@ const describeCases = config => {
let stderr;
beforeEach(() => {
stderr = captureStdio(process.stderr, true);
webpack = require("..");
});
afterEach(() => {
stderr.restore();
Expand Down

0 comments on commit 4e11778

Please sign in to comment.