This change modifies the build scripts to use --legacy-peer-deps flag when installing npm dependencies to resolve potential peer dependency conflicts during the build process. The change is applied to both bash (build.sh) and batch (build.bat) build scripts.
174 lines
5.3 KiB
JavaScript
174 lines
5.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* @fileoverview Main CLI that is run via the eslint command.
|
|
* @author Nicholas C. Zakas
|
|
*/
|
|
|
|
/* eslint no-console:off -- CLI */
|
|
|
|
"use strict";
|
|
|
|
// must do this initialization *before* other requires in order to work
|
|
if (process.argv.includes("--debug")) {
|
|
require("debug").enable("eslint:*,-eslint:code-path,eslintrc:*");
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Helpers
|
|
//------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Read data from stdin til the end.
|
|
*
|
|
* Note: See
|
|
* - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
|
|
* - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
|
|
* - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
|
|
* - https://github.com/nodejs/node/issues/7439 (historical)
|
|
*
|
|
* On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
|
|
* to read 4096 bytes before blocking and never drains to read further data.
|
|
*
|
|
* The investigation on the Emacs thread indicates:
|
|
*
|
|
* > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
|
|
* > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
|
|
* > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
|
|
* > the subprocess to read its end of the pipe, at which time Emacs will
|
|
* > write the rest of the stuff.
|
|
* @returns {Promise<string>} The read text.
|
|
*/
|
|
function readStdin() {
|
|
return new Promise((resolve, reject) => {
|
|
let content = "";
|
|
let chunk = "";
|
|
|
|
process.stdin
|
|
.setEncoding("utf8")
|
|
.on("readable", () => {
|
|
while ((chunk = process.stdin.read()) !== null) {
|
|
content += chunk;
|
|
}
|
|
})
|
|
.on("end", () => resolve(content))
|
|
.on("error", reject);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get the error message of a given value.
|
|
* @param {any} error The value to get.
|
|
* @returns {string} The error message.
|
|
*/
|
|
function getErrorMessage(error) {
|
|
|
|
// Lazy loading because this is used only if an error happened.
|
|
const util = require("util");
|
|
|
|
// Foolproof -- third-party module might throw non-object.
|
|
if (typeof error !== "object" || error === null) {
|
|
return String(error);
|
|
}
|
|
|
|
// Use templates if `error.messageTemplate` is present.
|
|
if (typeof error.messageTemplate === "string") {
|
|
try {
|
|
const template = require(`../messages/${error.messageTemplate}.js`);
|
|
|
|
return template(error.messageData || {});
|
|
} catch {
|
|
|
|
// Ignore template error then fallback to use `error.stack`.
|
|
}
|
|
}
|
|
|
|
// Use the stacktrace if it's an error object.
|
|
if (typeof error.stack === "string") {
|
|
return error.stack;
|
|
}
|
|
|
|
// Otherwise, dump the object.
|
|
return util.format("%o", error);
|
|
}
|
|
|
|
/**
|
|
* Tracks error messages that are shown to the user so we only ever show the
|
|
* same message once.
|
|
* @type {Set<string>}
|
|
*/
|
|
const displayedErrors = new Set();
|
|
|
|
/**
|
|
* Tracks whether an unexpected error was caught
|
|
* @type {boolean}
|
|
*/
|
|
let hadFatalError = false;
|
|
|
|
/**
|
|
* Catch and report unexpected error.
|
|
* @param {any} error The thrown error object.
|
|
* @returns {void}
|
|
*/
|
|
function onFatalError(error) {
|
|
process.exitCode = 2;
|
|
hadFatalError = true;
|
|
|
|
const { version } = require("../package.json");
|
|
const message = `
|
|
Oops! Something went wrong! :(
|
|
|
|
ESLint: ${version}
|
|
|
|
${getErrorMessage(error)}`;
|
|
|
|
if (!displayedErrors.has(message)) {
|
|
console.error(message);
|
|
displayedErrors.add(message);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Execution
|
|
//------------------------------------------------------------------------------
|
|
|
|
(async function main() {
|
|
process.on("uncaughtException", onFatalError);
|
|
process.on("unhandledRejection", onFatalError);
|
|
|
|
// Call the config initializer if `--init` is present.
|
|
if (process.argv.includes("--init")) {
|
|
|
|
// `eslint --init` has been moved to `@eslint/create-config`
|
|
console.warn("You can also run this command directly using 'npm init @eslint/config'.");
|
|
|
|
const spawn = require("cross-spawn");
|
|
|
|
spawn.sync("npm", ["init", "@eslint/config"], { encoding: "utf8", stdio: "inherit" });
|
|
return;
|
|
}
|
|
|
|
// Otherwise, call the CLI.
|
|
const exitCode = await require("../lib/cli").execute(
|
|
process.argv,
|
|
process.argv.includes("--stdin") ? await readStdin() : null,
|
|
true
|
|
);
|
|
|
|
/*
|
|
* If an uncaught exception or unhandled rejection was detected in the meantime,
|
|
* keep the fatal exit code 2 that is already assigned to `process.exitCode`.
|
|
* Without this condition, exit code 2 (unsuccessful execution) could be overwritten with
|
|
* 1 (successful execution, lint problems found) or even 0 (successful execution, no lint problems found).
|
|
* This ensures that unexpected errors that seemingly don't affect the success
|
|
* of the execution will still cause a non-zero exit code, as it's a common
|
|
* practice and the default behavior of Node.js to exit with non-zero
|
|
* in case of an uncaught exception or unhandled rejection.
|
|
*
|
|
* Otherwise, assign the exit code returned from CLI.
|
|
*/
|
|
if (!hadFatalError) {
|
|
process.exitCode = exitCode;
|
|
}
|
|
}()).catch(onFatalError);
|