| 
						 | 
						- /**
 -  * @fileoverview Main CLI object.
 -  * @author Nicholas C. Zakas
 -  */
 - 
 - "use strict";
 - 
 - /*
 -  * NOTE: The CLI object should *not* call process.exit() directly. It should only return
 -  * exit codes. This allows other programs to use the CLI object and still control
 -  * when the program exits.
 -  */
 - 
 - //------------------------------------------------------------------------------
 - // Requirements
 - //------------------------------------------------------------------------------
 - 
 - const fs = require("fs"),
 -     path = require("path"),
 -     { promisify } = require("util"),
 -     { ESLint } = require("./eslint"),
 -     { FlatESLint, shouldUseFlatConfig } = require("./eslint/flat-eslint"),
 -     createCLIOptions = require("./options"),
 -     log = require("./shared/logging"),
 -     RuntimeInfo = require("./shared/runtime-info"),
 -     { normalizeSeverityToString } = require("./shared/severity");
 - const { Legacy: { naming } } = require("@eslint/eslintrc");
 - const { ModuleImporter } = require("@humanwhocodes/module-importer");
 - 
 - const debug = require("debug")("eslint:cli");
 - 
 - //------------------------------------------------------------------------------
 - // Types
 - //------------------------------------------------------------------------------
 - 
 - /** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */
 - /** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
 - /** @typedef {import("./eslint/eslint").LintResult} LintResult */
 - /** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */
 - /** @typedef {import("./shared/types").ResultsMeta} ResultsMeta */
 - 
 - //------------------------------------------------------------------------------
 - // Helpers
 - //------------------------------------------------------------------------------
 - 
 - const mkdir = promisify(fs.mkdir);
 - const stat = promisify(fs.stat);
 - const writeFile = promisify(fs.writeFile);
 - 
 - /**
 -  * Predicate function for whether or not to apply fixes in quiet mode.
 -  * If a message is a warning, do not apply a fix.
 -  * @param {LintMessage} message The lint result.
 -  * @returns {boolean} True if the lint message is an error (and thus should be
 -  * autofixed), false otherwise.
 -  */
 - function quietFixPredicate(message) {
 -     return message.severity === 2;
 - }
 - 
 - /**
 -  * Translates the CLI options into the options expected by the ESLint constructor.
 -  * @param {ParsedCLIOptions} cliOptions The CLI options to translate.
 -  * @param {"flat"|"eslintrc"} [configType="eslintrc"] The format of the
 -  *      config to generate.
 -  * @returns {Promise<ESLintOptions>} The options object for the ESLint constructor.
 -  * @private
 -  */
 - async function translateOptions({
 -     cache,
 -     cacheFile,
 -     cacheLocation,
 -     cacheStrategy,
 -     config,
 -     configLookup,
 -     env,
 -     errorOnUnmatchedPattern,
 -     eslintrc,
 -     ext,
 -     fix,
 -     fixDryRun,
 -     fixType,
 -     global,
 -     ignore,
 -     ignorePath,
 -     ignorePattern,
 -     inlineConfig,
 -     parser,
 -     parserOptions,
 -     plugin,
 -     quiet,
 -     reportUnusedDisableDirectives,
 -     reportUnusedDisableDirectivesSeverity,
 -     resolvePluginsRelativeTo,
 -     rule,
 -     rulesdir,
 -     warnIgnored
 - }, configType) {
 - 
 -     let overrideConfig, overrideConfigFile;
 -     const importer = new ModuleImporter();
 - 
 -     if (configType === "flat") {
 -         overrideConfigFile = (typeof config === "string") ? config : !configLookup;
 -         if (overrideConfigFile === false) {
 -             overrideConfigFile = void 0;
 -         }
 - 
 -         let globals = {};
 - 
 -         if (global) {
 -             globals = global.reduce((obj, name) => {
 -                 if (name.endsWith(":true")) {
 -                     obj[name.slice(0, -5)] = "writable";
 -                 } else {
 -                     obj[name] = "readonly";
 -                 }
 -                 return obj;
 -             }, globals);
 -         }
 - 
 -         overrideConfig = [{
 -             languageOptions: {
 -                 globals,
 -                 parserOptions: parserOptions || {}
 -             },
 -             rules: rule ? rule : {}
 -         }];
 - 
 -         if (reportUnusedDisableDirectives || reportUnusedDisableDirectivesSeverity !== void 0) {
 -             overrideConfig[0].linterOptions = {
 -                 reportUnusedDisableDirectives: reportUnusedDisableDirectives
 -                     ? "error"
 -                     : normalizeSeverityToString(reportUnusedDisableDirectivesSeverity)
 -             };
 -         }
 - 
 -         if (parser) {
 -             overrideConfig[0].languageOptions.parser = await importer.import(parser);
 -         }
 - 
 -         if (plugin) {
 -             const plugins = {};
 - 
 -             for (const pluginName of plugin) {
 - 
 -                 const shortName = naming.getShorthandName(pluginName, "eslint-plugin");
 -                 const longName = naming.normalizePackageName(pluginName, "eslint-plugin");
 - 
 -                 plugins[shortName] = await importer.import(longName);
 -             }
 - 
 -             overrideConfig[0].plugins = plugins;
 -         }
 - 
 -     } else {
 -         overrideConfigFile = config;
 - 
 -         overrideConfig = {
 -             env: env && env.reduce((obj, name) => {
 -                 obj[name] = true;
 -                 return obj;
 -             }, {}),
 -             globals: global && global.reduce((obj, name) => {
 -                 if (name.endsWith(":true")) {
 -                     obj[name.slice(0, -5)] = "writable";
 -                 } else {
 -                     obj[name] = "readonly";
 -                 }
 -                 return obj;
 -             }, {}),
 -             ignorePatterns: ignorePattern,
 -             parser,
 -             parserOptions,
 -             plugins: plugin,
 -             rules: rule
 -         };
 -     }
 - 
 -     const options = {
 -         allowInlineConfig: inlineConfig,
 -         cache,
 -         cacheLocation: cacheLocation || cacheFile,
 -         cacheStrategy,
 -         errorOnUnmatchedPattern,
 -         fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
 -         fixTypes: fixType,
 -         ignore,
 -         overrideConfig,
 -         overrideConfigFile
 -     };
 - 
 -     if (configType === "flat") {
 -         options.ignorePatterns = ignorePattern;
 -         options.warnIgnored = warnIgnored;
 -     } else {
 -         options.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
 -         options.rulePaths = rulesdir;
 -         options.useEslintrc = eslintrc;
 -         options.extensions = ext;
 -         options.ignorePath = ignorePath;
 -         if (reportUnusedDisableDirectives || reportUnusedDisableDirectivesSeverity !== void 0) {
 -             options.reportUnusedDisableDirectives = reportUnusedDisableDirectives
 -                 ? "error"
 -                 : normalizeSeverityToString(reportUnusedDisableDirectivesSeverity);
 -         }
 -     }
 - 
 -     return options;
 - }
 - 
 - /**
 -  * Count error messages.
 -  * @param {LintResult[]} results The lint results.
 -  * @returns {{errorCount:number;fatalErrorCount:number,warningCount:number}} The number of error messages.
 -  */
 - function countErrors(results) {
 -     let errorCount = 0;
 -     let fatalErrorCount = 0;
 -     let warningCount = 0;
 - 
 -     for (const result of results) {
 -         errorCount += result.errorCount;
 -         fatalErrorCount += result.fatalErrorCount;
 -         warningCount += result.warningCount;
 -     }
 - 
 -     return { errorCount, fatalErrorCount, warningCount };
 - }
 - 
 - /**
 -  * Check if a given file path is a directory or not.
 -  * @param {string} filePath The path to a file to check.
 -  * @returns {Promise<boolean>} `true` if the given path is a directory.
 -  */
 - async function isDirectory(filePath) {
 -     try {
 -         return (await stat(filePath)).isDirectory();
 -     } catch (error) {
 -         if (error.code === "ENOENT" || error.code === "ENOTDIR") {
 -             return false;
 -         }
 -         throw error;
 -     }
 - }
 - 
 - /**
 -  * Outputs the results of the linting.
 -  * @param {ESLint} engine The ESLint instance to use.
 -  * @param {LintResult[]} results The results to print.
 -  * @param {string} format The name of the formatter to use or the path to the formatter.
 -  * @param {string} outputFile The path for the output file.
 -  * @param {ResultsMeta} resultsMeta Warning count and max threshold.
 -  * @returns {Promise<boolean>} True if the printing succeeds, false if not.
 -  * @private
 -  */
 - async function printResults(engine, results, format, outputFile, resultsMeta) {
 -     let formatter;
 - 
 -     try {
 -         formatter = await engine.loadFormatter(format);
 -     } catch (e) {
 -         log.error(e.message);
 -         return false;
 -     }
 - 
 -     const output = await formatter.format(results, resultsMeta);
 - 
 -     if (output) {
 -         if (outputFile) {
 -             const filePath = path.resolve(process.cwd(), outputFile);
 - 
 -             if (await isDirectory(filePath)) {
 -                 log.error("Cannot write to output file path, it is a directory: %s", outputFile);
 -                 return false;
 -             }
 - 
 -             try {
 -                 await mkdir(path.dirname(filePath), { recursive: true });
 -                 await writeFile(filePath, output);
 -             } catch (ex) {
 -                 log.error("There was a problem writing the output file:\n%s", ex);
 -                 return false;
 -             }
 -         } else {
 -             log.info(output);
 -         }
 -     }
 - 
 -     return true;
 - }
 - 
 - //------------------------------------------------------------------------------
 - // Public Interface
 - //------------------------------------------------------------------------------
 - 
 - /**
 -  * Encapsulates all CLI behavior for eslint. Makes it easier to test as well as
 -  * for other Node.js programs to effectively run the CLI.
 -  */
 - const cli = {
 - 
 -     /**
 -      * Executes the CLI based on an array of arguments that is passed in.
 -      * @param {string|Array|Object} args The arguments to process.
 -      * @param {string} [text] The text to lint (used for TTY).
 -      * @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
 -      * @returns {Promise<number>} The exit code for the operation.
 -      */
 -     async execute(args, text, allowFlatConfig) {
 -         if (Array.isArray(args)) {
 -             debug("CLI args: %o", args.slice(2));
 -         }
 - 
 -         /*
 -          * Before doing anything, we need to see if we are using a
 -          * flat config file. If so, then we need to change the way command
 -          * line args are parsed. This is temporary, and when we fully
 -          * switch to flat config we can remove this logic.
 -          */
 - 
 -         const usingFlatConfig = allowFlatConfig && await shouldUseFlatConfig();
 - 
 -         debug("Using flat config?", usingFlatConfig);
 - 
 -         const CLIOptions = createCLIOptions(usingFlatConfig);
 - 
 -         /** @type {ParsedCLIOptions} */
 -         let options;
 - 
 -         try {
 -             options = CLIOptions.parse(args);
 -         } catch (error) {
 -             debug("Error parsing CLI options:", error.message);
 - 
 -             let errorMessage = error.message;
 - 
 -             if (usingFlatConfig) {
 -                 errorMessage += "\nYou're using eslint.config.js, some command line flags are no longer available. Please see https://eslint.org/docs/latest/use/command-line-interface for details.";
 -             }
 - 
 -             log.error(errorMessage);
 -             return 2;
 -         }
 - 
 -         const files = options._;
 -         const useStdin = typeof text === "string";
 - 
 -         if (options.help) {
 -             log.info(CLIOptions.generateHelp());
 -             return 0;
 -         }
 -         if (options.version) {
 -             log.info(RuntimeInfo.version());
 -             return 0;
 -         }
 -         if (options.envInfo) {
 -             try {
 -                 log.info(RuntimeInfo.environment());
 -                 return 0;
 -             } catch (err) {
 -                 debug("Error retrieving environment info");
 -                 log.error(err.message);
 -                 return 2;
 -             }
 -         }
 - 
 -         if (options.printConfig) {
 -             if (files.length) {
 -                 log.error("The --print-config option must be used with exactly one file name.");
 -                 return 2;
 -             }
 -             if (useStdin) {
 -                 log.error("The --print-config option is not available for piped-in code.");
 -                 return 2;
 -             }
 - 
 -             const engine = usingFlatConfig
 -                 ? new FlatESLint(await translateOptions(options, "flat"))
 -                 : new ESLint(await translateOptions(options));
 -             const fileConfig =
 -                 await engine.calculateConfigForFile(options.printConfig);
 - 
 -             log.info(JSON.stringify(fileConfig, null, "  "));
 -             return 0;
 -         }
 - 
 -         debug(`Running on ${useStdin ? "text" : "files"}`);
 - 
 -         if (options.fix && options.fixDryRun) {
 -             log.error("The --fix option and the --fix-dry-run option cannot be used together.");
 -             return 2;
 -         }
 -         if (useStdin && options.fix) {
 -             log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
 -             return 2;
 -         }
 -         if (options.fixType && !options.fix && !options.fixDryRun) {
 -             log.error("The --fix-type option requires either --fix or --fix-dry-run.");
 -             return 2;
 -         }
 - 
 -         if (options.reportUnusedDisableDirectives && options.reportUnusedDisableDirectivesSeverity !== void 0) {
 -             log.error("The --report-unused-disable-directives option and the --report-unused-disable-directives-severity option cannot be used together.");
 -             return 2;
 -         }
 - 
 -         const ActiveESLint = usingFlatConfig ? FlatESLint : ESLint;
 - 
 -         const engine = new ActiveESLint(await translateOptions(options, usingFlatConfig ? "flat" : "eslintrc"));
 -         let results;
 - 
 -         if (useStdin) {
 -             results = await engine.lintText(text, {
 -                 filePath: options.stdinFilename,
 - 
 -                 // flatConfig respects CLI flag and constructor warnIgnored, eslintrc forces true for backwards compatibility
 -                 warnIgnored: usingFlatConfig ? void 0 : true
 -             });
 -         } else {
 -             results = await engine.lintFiles(files);
 -         }
 - 
 -         if (options.fix) {
 -             debug("Fix mode enabled - applying fixes");
 -             await ActiveESLint.outputFixes(results);
 -         }
 - 
 -         let resultsToPrint = results;
 - 
 -         if (options.quiet) {
 -             debug("Quiet mode enabled - filtering out warnings");
 -             resultsToPrint = ActiveESLint.getErrorResults(resultsToPrint);
 -         }
 - 
 -         const resultCounts = countErrors(results);
 -         const tooManyWarnings = options.maxWarnings >= 0 && resultCounts.warningCount > options.maxWarnings;
 -         const resultsMeta = tooManyWarnings
 -             ? {
 -                 maxWarningsExceeded: {
 -                     maxWarnings: options.maxWarnings,
 -                     foundWarnings: resultCounts.warningCount
 -                 }
 -             }
 -             : {};
 - 
 -         if (await printResults(engine, resultsToPrint, options.format, options.outputFile, resultsMeta)) {
 - 
 -             // Errors and warnings from the original unfiltered results should determine the exit code
 -             const shouldExitForFatalErrors =
 -                 options.exitOnFatalError && resultCounts.fatalErrorCount > 0;
 - 
 -             if (!resultCounts.errorCount && tooManyWarnings) {
 -                 log.error(
 -                     "ESLint found too many warnings (maximum: %s).",
 -                     options.maxWarnings
 -                 );
 -             }
 - 
 -             if (shouldExitForFatalErrors) {
 -                 return 2;
 -             }
 - 
 -             return (resultCounts.errorCount || tooManyWarnings) ? 1 : 0;
 -         }
 - 
 -         return 2;
 -     }
 - };
 - 
 - module.exports = cli;
 
 
  |