Skip to content

Commit

Permalink
[BREAKING] Replace console.log with process.stderr (#686)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
System messages will now be written to stderr instead of stdout.

JIRA: CPOUI5FOUNDATION-802
Related to: SAP/ui5-tooling#701
Sibling of: SAP/ui5-server#643,
SAP/ui5-tooling#930
  • Loading branch information
d3xter666 authored Feb 29, 2024
1 parent 772ac29 commit 48d1975
Show file tree
Hide file tree
Showing 18 changed files with 248 additions and 181 deletions.
58 changes: 36 additions & 22 deletions bin/ui5.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,37 @@ const ui5 = {
pkg.engines && pkg.engines.node &&
(!semver || !semver.satisfies(nodeVersion, pkg.engines.node, {includePrerelease: true}))
) {
console.log("==================== UNSUPPORTED NODE.JS VERSION ====================");
console.log("You are using an unsupported version of Node.js");
console.log("Detected version " + nodeVersion + " but " + pkg.name + " requires " + pkg.engines.node);
console.log("");
console.log("=> Please upgrade to a supported version of Node.js to use this tool");
console.log("=====================================================================");
process.stderr.write("==================== UNSUPPORTED NODE.JS VERSION ====================");
process.stderr.write("\n");
process.stderr.write("You are using an unsupported version of Node.js");
process.stderr.write("\n");
process.stderr.write("Detected version " + nodeVersion +
" but " + pkg.name + " requires " + pkg.engines.node);
process.stderr.write("\n\n");
process.stderr.write("=> Please upgrade to a supported version of Node.js to use this tool");
process.stderr.write("\n");
process.stderr.write("=====================================================================");
process.stderr.write("\n");
return false;
}

if (semver && semver.prerelease(nodeVersion)) {
console.log("====================== UNSTABLE NODE.JS VERSION =====================");
console.log("You are using an unstable version of Node.js");
console.log("Detected Node.js version " + nodeVersion);
console.log("");
console.log("=> Please note that an unstable version might cause unexpected");
console.log(" behavior. For productive use please consider using a stable");
console.log(" version of Node.js! For the release policy of Node.js, see");
console.log(" https://nodejs.org/en/about/releases");
console.log("=====================================================================");
process.stderr.write("====================== UNSTABLE NODE.JS VERSION =====================");
process.stderr.write("\n");
process.stderr.write("You are using an unstable version of Node.js");
process.stderr.write("\n");
process.stderr.write("Detected Node.js version " + nodeVersion);
process.stderr.write("\n\n");
process.stderr.write("=> Please note that an unstable version might cause unexpected");
process.stderr.write("\n");
process.stderr.write(" behavior. For productive use please consider using a stable");
process.stderr.write("\n");
process.stderr.write(" version of Node.js! For the release policy of Node.js, see");
process.stderr.write("\n");
process.stderr.write(" https://nodejs.org/en/about/releases");
process.stderr.write("\n");
process.stderr.write("=====================================================================");
process.stderr.write("\n");
}

return true;
Expand All @@ -65,13 +77,14 @@ const ui5 = {
return false;
}
if (process.argv.includes("--verbose")) {
console.info(`INFO: This project contains an individual ${pkg.name} installation which ` +
process.stderr.write(`INFO: This project contains an individual ${pkg.name} installation which ` +
"will be used over the global one.");
console.info("See https://github.com/SAP/ui5-cli#local-vs-global-installation for details.");
console.info("");
process.stderr.write("\n");
process.stderr.write("See https://github.com/SAP/ui5-cli#local-vs-global-installation for details.");
process.stderr.write("\n\n");
} else {
console.info(`INFO: Using local ${pkg.name} installation`);
console.info("");
process.stdout.write(`INFO: Using local ${pkg.name} installation`);
process.stdout.write("\n\n");
}
return true;
},
Expand All @@ -98,8 +111,9 @@ module.exports = ui5;

if (process.env.NODE_ENV !== "test" || process.env.UI5_CLI_TEST_BIN_RUN_MAIN !== "false") {
ui5.main().catch((err) => {
console.log("Fatal Error: Unable to initialize UI5 CLI");
console.log(err);
process.stderr.write("Fatal Error: Unable to initialize UI5 CLI");
process.stderr.write("\n");
process.stderr.write(err);
process.exit(1);
});
}
39 changes: 23 additions & 16 deletions lib/cli/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,37 +91,44 @@ export default function(cli) {
ConsoleWriter.stop();
// Exception
if (isLogLevelEnabled("error")) {
console.log("");
console.log(chalk.bold.red("⚠️ Process Failed With Error"));
process.stderr.write("\n");
process.stderr.write(chalk.bold.red("⚠️ Process Failed With Error"));

console.log("");
console.log(chalk.underline("Error Message:"));
console.log(err.message);
process.stderr.write("\n\n");
process.stderr.write(chalk.underline("Error Message:"));
process.stderr.write("\n");
process.stderr.write(err.message);
process.stderr.write("\n");

// Unexpected errors should always be logged with stack trace
const unexpectedErrors = ["SyntaxError", "ReferenceError", "TypeError"];
if (unexpectedErrors.includes(err.name) || isLogLevelEnabled("verbose")) {
console.log("");
console.log(chalk.underline("Stack Trace:"));
console.log(err.stack);
console.log("");
console.log(
process.stderr.write("\n\n");
process.stderr.write(chalk.underline("Stack Trace:"));
process.stderr.write("\n");
process.stderr.write(err.stack);
process.stderr.write("\n");
process.stderr.write(
chalk.dim(
`If you think this is an issue of the UI5 Tooling, you might report it using the ` +
`following URL: `) +
chalk.dim.bold.underline(`https://github.com/SAP/ui5-tooling/issues/new/choose`));
process.stderr.write("\n");
} else {
console.log("");
console.log(chalk.dim(
process.stderr.write("\n\n");
process.stderr.write(chalk.dim(
`For details, execute the same command again with an additional '--verbose' parameter`));
process.stderr.write("\n");
}
}
} else {
// Yargs error
console.log(chalk.bold.yellow("Command Failed:"));
console.log(`${msg}`);
console.log("");
console.log(chalk.dim(`See 'ui5 --help'`));
process.stderr.write(chalk.bold.yellow("Command Failed:"));
process.stderr.write("\n");
process.stderr.write(`${msg}`);
process.stderr.write("\n\n");
process.stderr.write(chalk.dim(`See 'ui5 --help'`));
process.stderr.write("\n");
}
process.exit(1);
});
Expand Down
6 changes: 4 additions & 2 deletions lib/cli/commands/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,17 @@ addCommand.handler = async function(argv) {
);
}
} else {
console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
process.stdout.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
process.stdout.write("\n");
let logMessage = `Added framework ${library} ${libraryNames.join(" ")} as`;
if (development) {
logMessage += " development";
} else if (optional) {
logMessage += " optional";
}
logMessage += libraries.length === 1 ? " dependency": " dependencies";
console.log(logMessage);
process.stdout.write(logMessage);
process.stdout.write("\n");
}
};

Expand Down
6 changes: 4 additions & 2 deletions lib/cli/commands/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ initCommand.handler = async function() {
const yaml = jsYaml.dump(projectConfig, {quotingType: `"`});

await writeFile(yamlPath, yaml);
console.log(`Wrote ui5.yaml to ${yamlPath}:\n`);
console.log(yaml);
process.stdout.write(`Wrote ui5.yaml to ${yamlPath}:`);
process.stdout.write("\n");
process.stdout.write(yaml);
process.stdout.write("\n");
};

export default initCommand;
6 changes: 4 additions & 2 deletions lib/cli/commands/remove.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ removeCommand.handler = async function(argv) {
);
}
} else {
console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
process.stdout.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
process.stdout.write("\n");
let logMessage = `Removed framework ${library} ${libraryNames.join(" ")} as`;
logMessage += libraries.length === 1 ? " dependency": " dependencies";
console.log(logMessage);
process.stdout.write(logMessage);
process.stdout.write("\n");
}
};

Expand Down
24 changes: 15 additions & 9 deletions lib/cli/commands/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,26 @@ serve.handler = async function(argv) {
const protocol = h2 ? "https" : "http";
let browserUrl = protocol + "://localhost:" + actualPort;
if (argv.acceptRemoteConnections) {
console.log("");
console.log(chalk.bold("⚠️ This server is accepting connections from all hosts on your network"));
console.log(chalk.dim.underline("Please Note:"));
console.log(chalk.bold.dim(
process.stderr.write("\n");
process.stderr.write(chalk.bold("⚠️ This server is accepting connections from all hosts on your network"));
process.stderr.write("\n");
process.stderr.write(chalk.dim.underline("Please Note:"));
process.stderr.write("\n");
process.stderr.write(chalk.bold.dim(
"* This server is intended for development purposes only. Do not use it in production."));
console.log(chalk.dim(
process.stderr.write("\n");
process.stderr.write(chalk.dim(
"* Vulnerable (custom-)middleware can pose a threat to your system when exposed to the network"));
console.log(chalk.dim(
process.stderr.write("\n");
process.stderr.write(chalk.dim(
"* The use of proxy-middleware with preconfigured credentials might enable unauthorized access " +
"to a target system for third parties on your network"));
console.log("");
process.stderr.write("\n\n");
}
console.log("Server started");
console.log("URL: " + browserUrl);
process.stdout.write("Server started");
process.stdout.write("\n");
process.stdout.write("URL: " + browserUrl);
process.stdout.write("\n");

if (argv.open !== undefined) {
if (typeof argv.open === "string") {
Expand Down
25 changes: 16 additions & 9 deletions lib/cli/commands/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,13 @@ tree.handler = async function(argv) {
if (project.isFrameworkProject()) {
name = chalk.blue(name);
}
console.log(
process.stdout.write(
`${baseString}${connectorString} ${name} ` +
`${project.getNamespace() ? chalk.inverse(project.getNamespace()) + " " : ""}` +
chalk.dim(`(${project.getVersion()}, ${project.getType()}) `) +
chalk.dim.italic(`${project.getRootPath()}`)
);
process.stdout.write("\n");

const lastIdx = dependencies.length - 1;
const newConnectorIndices = [...connectorIndices];
Expand All @@ -109,7 +110,8 @@ tree.handler = async function(argv) {
newConnectorIndices.forEach((idx) => {
nextBaseString = `${nextBaseString.slice(0, idx)}${nextBaseString.slice(idx + 1)}`;
});
console.log(`${nextBaseString}╰─ ${msg}`);
process.stdout.write(`${nextBaseString}╰─ ${msg}`);
process.stdout.write("\n");
return;
}
if (renderDeps) {
Expand All @@ -121,7 +123,8 @@ tree.handler = async function(argv) {
});
});

console.log(chalk.bold.underline(`Dependencies (${projects.size}):`));
process.stdout.write(chalk.bold.underline(`Dependencies (${projects.size}):`));
process.stdout.write("\n");
if (argv.flat) {
// Iterate over list of projects, rendering each individually
// We need to transform the map into an array in order to know the index
Expand All @@ -133,28 +136,32 @@ tree.handler = async function(argv) {
// Recursively render the tree, starting with the first entry of the map
projects.values().next().value.render(0, [], true);
}
console.log("");
process.stdout.write("\n");

const extensionNames = graph.getExtensionNames();
const extensionCount = extensionNames.length;
console.log(chalk.bold.underline(`Extensions (${extensionCount}):`));
process.stdout.write(chalk.bold.underline(`Extensions (${extensionCount}):`));
process.stdout.write("\n");
if (extensionCount) {
const lastIdx = extensionCount - 1;
extensionNames.forEach((extensionName, idx) => {
const extension = graph.getExtension(extensionName);
const connectorString = idx === lastIdx ? "╰─" : "├─";
console.log(
process.stdout.write(
`${connectorString} ${extensionName} ` +
chalk.dim(`(${extension.getVersion()}, ${extension.getType()}) `) +
chalk.dim.italic(`${extension.getRootPath()}`));
process.stdout.write("\n");
});
} else {
console.log(chalk.italic(`None`));
process.stdout.write(chalk.italic(`None`));
process.stdout.write("\n");
}
if (argv.perf) {
console.log("");
console.log(chalk.blue(
process.stderr.write("\n");
process.stderr.write(chalk.blue(
`Dependency graph generation took ${chalk.bold(elapsedTime)}`));
process.stderr.write("\n");
}
};

Expand Down
6 changes: 4 additions & 2 deletions lib/cli/commands/use.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,10 @@ useCommand.handler = async function(argv) {
throw new Error(`Internal error while updating ui5.yaml to ${usedFramework} version ${usedVersion}`);
}
} else {
console.log(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
console.log(`This project is now using ${usedFramework} version ${usedVersion}`);
process.stdout.write(`Updated configuration written to ${argv.config || "ui5.yaml"}`);
process.stdout.write("\n");
process.stdout.write(`This project is now using ${usedFramework} version ${usedVersion}`);
process.stdout.write("\n");
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/cli/commands/versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ versions.handler = async function() {
})
)).join("\n");

console.log(`\n${output}\n`);
process.stdout.write(`\n${output}\n\n`);
};

export default versions;
Loading

0 comments on commit 48d1975

Please sign in to comment.