| 
						 | 
						- /**
 -  * @fileoverview `CascadingConfigArrayFactory` class.
 -  *
 -  * `CascadingConfigArrayFactory` class has a responsibility:
 -  *
 -  * 1. Handles cascading of config files.
 -  *
 -  * It provides two methods:
 -  *
 -  * - `getConfigArrayForFile(filePath)`
 -  *     Get the corresponded configuration of a given file. This method doesn't
 -  *     throw even if the given file didn't exist.
 -  * - `clearCache()`
 -  *     Clear the internal cache. You have to call this method when
 -  *     `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
 -  *     on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
 -  *
 -  * @author Toru Nagashima <https://github.com/mysticatea>
 -  */
 - 
 - //------------------------------------------------------------------------------
 - // Requirements
 - //------------------------------------------------------------------------------
 - 
 - import debugOrig from "debug";
 - import os from "os";
 - import path from "path";
 - 
 - import { ConfigArrayFactory } from "./config-array-factory.js";
 - import {
 -     ConfigArray,
 -     ConfigDependency,
 -     IgnorePattern
 - } from "./config-array/index.js";
 - import ConfigValidator from "./shared/config-validator.js";
 - import { emitDeprecationWarning } from "./shared/deprecation-warnings.js";
 - 
 - const debug = debugOrig("eslintrc:cascading-config-array-factory");
 - 
 - //------------------------------------------------------------------------------
 - // Helpers
 - //------------------------------------------------------------------------------
 - 
 - // Define types for VSCode IntelliSense.
 - /** @typedef {import("./shared/types").ConfigData} ConfigData */
 - /** @typedef {import("./shared/types").Parser} Parser */
 - /** @typedef {import("./shared/types").Plugin} Plugin */
 - /** @typedef {import("./shared/types").Rule} Rule */
 - /** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
 - 
 - /**
 -  * @typedef {Object} CascadingConfigArrayFactoryOptions
 -  * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
 -  * @property {ConfigData} [baseConfig] The config by `baseConfig` option.
 -  * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.
 -  * @property {string} [cwd] The base directory to start lookup.
 -  * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
 -  * @property {string[]} [rulePaths] The value of `--rulesdir` option.
 -  * @property {string} [specificConfigPath] The value of `--config` option.
 -  * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
 -  * @property {Function} loadRules The function to use to load rules.
 -  * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
 -  * @property {Object} [resolver=ModuleResolver] The module resolver object.
 -  * @property {string} eslintAllPath The path to the definitions for eslint:all.
 -  * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
 -  * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
 -  * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
 -  */
 - 
 - /**
 -  * @typedef {Object} CascadingConfigArrayFactoryInternalSlots
 -  * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
 -  * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
 -  * @property {ConfigArray} cliConfigArray The config array of CLI options.
 -  * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
 -  * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
 -  * @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
 -  * @property {string} cwd The base directory to start lookup.
 -  * @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
 -  * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
 -  * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
 -  * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
 -  * @property {boolean} useEslintrc if `false` then it doesn't load config files.
 -  * @property {Function} loadRules The function to use to load rules.
 -  * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
 -  * @property {Object} [resolver=ModuleResolver] The module resolver object.
 -  * @property {string} eslintAllPath The path to the definitions for eslint:all.
 -  * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
 -  * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
 -  * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
 -  */
 - 
 - /** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
 - const internalSlotsMap = new WeakMap();
 - 
 - /**
 -  * Create the config array from `baseConfig` and `rulePaths`.
 -  * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
 -  * @returns {ConfigArray} The config array of the base configs.
 -  */
 - function createBaseConfigArray({
 -     configArrayFactory,
 -     baseConfigData,
 -     rulePaths,
 -     cwd,
 -     loadRules
 - }) {
 -     const baseConfigArray = configArrayFactory.create(
 -         baseConfigData,
 -         { name: "BaseConfig" }
 -     );
 - 
 -     /*
 -      * Create the config array element for the default ignore patterns.
 -      * This element has `ignorePattern` property that ignores the default
 -      * patterns in the current working directory.
 -      */
 -     baseConfigArray.unshift(configArrayFactory.create(
 -         { ignorePatterns: IgnorePattern.DefaultPatterns },
 -         { name: "DefaultIgnorePattern" }
 -     )[0]);
 - 
 -     /*
 -      * Load rules `--rulesdir` option as a pseudo plugin.
 -      * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
 -      * the rule's options with only information in the config array.
 -      */
 -     if (rulePaths && rulePaths.length > 0) {
 -         baseConfigArray.push({
 -             type: "config",
 -             name: "--rulesdir",
 -             filePath: "",
 -             plugins: {
 -                 "": new ConfigDependency({
 -                     definition: {
 -                         rules: rulePaths.reduce(
 -                             (map, rulesPath) => Object.assign(
 -                                 map,
 -                                 loadRules(rulesPath, cwd)
 -                             ),
 -                             {}
 -                         )
 -                     },
 -                     filePath: "",
 -                     id: "",
 -                     importerName: "--rulesdir",
 -                     importerPath: ""
 -                 })
 -             }
 -         });
 -     }
 - 
 -     return baseConfigArray;
 - }
 - 
 - /**
 -  * Create the config array from CLI options.
 -  * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
 -  * @returns {ConfigArray} The config array of the base configs.
 -  */
 - function createCLIConfigArray({
 -     cliConfigData,
 -     configArrayFactory,
 -     cwd,
 -     ignorePath,
 -     specificConfigPath
 - }) {
 -     const cliConfigArray = configArrayFactory.create(
 -         cliConfigData,
 -         { name: "CLIOptions" }
 -     );
 - 
 -     cliConfigArray.unshift(
 -         ...(ignorePath
 -             ? configArrayFactory.loadESLintIgnore(ignorePath)
 -             : configArrayFactory.loadDefaultESLintIgnore())
 -     );
 - 
 -     if (specificConfigPath) {
 -         cliConfigArray.unshift(
 -             ...configArrayFactory.loadFile(
 -                 specificConfigPath,
 -                 { name: "--config", basePath: cwd }
 -             )
 -         );
 -     }
 - 
 -     return cliConfigArray;
 - }
 - 
 - /**
 -  * The error type when there are files matched by a glob, but all of them have been ignored.
 -  */
 - class ConfigurationNotFoundError extends Error {
 - 
 -     // eslint-disable-next-line jsdoc/require-description
 -     /**
 -      * @param {string} directoryPath The directory path.
 -      */
 -     constructor(directoryPath) {
 -         super(`No ESLint configuration found in ${directoryPath}.`);
 -         this.messageTemplate = "no-config-found";
 -         this.messageData = { directoryPath };
 -     }
 - }
 - 
 - /**
 -  * This class provides the functionality that enumerates every file which is
 -  * matched by given glob patterns and that configuration.
 -  */
 - class CascadingConfigArrayFactory {
 - 
 -     /**
 -      * Initialize this enumerator.
 -      * @param {CascadingConfigArrayFactoryOptions} options The options.
 -      */
 -     constructor({
 -         additionalPluginPool = new Map(),
 -         baseConfig: baseConfigData = null,
 -         cliConfig: cliConfigData = null,
 -         cwd = process.cwd(),
 -         ignorePath,
 -         resolvePluginsRelativeTo,
 -         rulePaths = [],
 -         specificConfigPath = null,
 -         useEslintrc = true,
 -         builtInRules = new Map(),
 -         loadRules,
 -         resolver,
 -         eslintRecommendedPath,
 -         getEslintRecommendedConfig,
 -         eslintAllPath,
 -         getEslintAllConfig
 -     } = {}) {
 -         const configArrayFactory = new ConfigArrayFactory({
 -             additionalPluginPool,
 -             cwd,
 -             resolvePluginsRelativeTo,
 -             builtInRules,
 -             resolver,
 -             eslintRecommendedPath,
 -             getEslintRecommendedConfig,
 -             eslintAllPath,
 -             getEslintAllConfig
 -         });
 - 
 -         internalSlotsMap.set(this, {
 -             baseConfigArray: createBaseConfigArray({
 -                 baseConfigData,
 -                 configArrayFactory,
 -                 cwd,
 -                 rulePaths,
 -                 loadRules
 -             }),
 -             baseConfigData,
 -             cliConfigArray: createCLIConfigArray({
 -                 cliConfigData,
 -                 configArrayFactory,
 -                 cwd,
 -                 ignorePath,
 -                 specificConfigPath
 -             }),
 -             cliConfigData,
 -             configArrayFactory,
 -             configCache: new Map(),
 -             cwd,
 -             finalizeCache: new WeakMap(),
 -             ignorePath,
 -             rulePaths,
 -             specificConfigPath,
 -             useEslintrc,
 -             builtInRules,
 -             loadRules
 -         });
 -     }
 - 
 -     /**
 -      * The path to the current working directory.
 -      * This is used by tests.
 -      * @type {string}
 -      */
 -     get cwd() {
 -         const { cwd } = internalSlotsMap.get(this);
 - 
 -         return cwd;
 -     }
 - 
 -     /**
 -      * Get the config array of a given file.
 -      * If `filePath` was not given, it returns the config which contains only
 -      * `baseConfigData` and `cliConfigData`.
 -      * @param {string} [filePath] The file path to a file.
 -      * @param {Object} [options] The options.
 -      * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
 -      * @returns {ConfigArray} The config array of the file.
 -      */
 -     getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
 -         const {
 -             baseConfigArray,
 -             cliConfigArray,
 -             cwd
 -         } = internalSlotsMap.get(this);
 - 
 -         if (!filePath) {
 -             return new ConfigArray(...baseConfigArray, ...cliConfigArray);
 -         }
 - 
 -         const directoryPath = path.dirname(path.resolve(cwd, filePath));
 - 
 -         debug(`Load config files for ${directoryPath}.`);
 - 
 -         return this._finalizeConfigArray(
 -             this._loadConfigInAncestors(directoryPath),
 -             directoryPath,
 -             ignoreNotFoundError
 -         );
 -     }
 - 
 -     /**
 -      * Set the config data to override all configs.
 -      * Require to call `clearCache()` method after this method is called.
 -      * @param {ConfigData} configData The config data to override all configs.
 -      * @returns {void}
 -      */
 -     setOverrideConfig(configData) {
 -         const slots = internalSlotsMap.get(this);
 - 
 -         slots.cliConfigData = configData;
 -     }
 - 
 -     /**
 -      * Clear config cache.
 -      * @returns {void}
 -      */
 -     clearCache() {
 -         const slots = internalSlotsMap.get(this);
 - 
 -         slots.baseConfigArray = createBaseConfigArray(slots);
 -         slots.cliConfigArray = createCLIConfigArray(slots);
 -         slots.configCache.clear();
 -     }
 - 
 -     /**
 -      * Load and normalize config files from the ancestor directories.
 -      * @param {string} directoryPath The path to a leaf directory.
 -      * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
 -      * @returns {ConfigArray} The loaded config.
 -      * @private
 -      */
 -     _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
 -         const {
 -             baseConfigArray,
 -             configArrayFactory,
 -             configCache,
 -             cwd,
 -             useEslintrc
 -         } = internalSlotsMap.get(this);
 - 
 -         if (!useEslintrc) {
 -             return baseConfigArray;
 -         }
 - 
 -         let configArray = configCache.get(directoryPath);
 - 
 -         // Hit cache.
 -         if (configArray) {
 -             debug(`Cache hit: ${directoryPath}.`);
 -             return configArray;
 -         }
 -         debug(`No cache found: ${directoryPath}.`);
 - 
 -         const homePath = os.homedir();
 - 
 -         // Consider this is root.
 -         if (directoryPath === homePath && cwd !== homePath) {
 -             debug("Stop traversing because of considered root.");
 -             if (configsExistInSubdirs) {
 -                 const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
 - 
 -                 if (filePath) {
 -                     emitDeprecationWarning(
 -                         filePath,
 -                         "ESLINT_PERSONAL_CONFIG_SUPPRESS"
 -                     );
 -                 }
 -             }
 -             return this._cacheConfig(directoryPath, baseConfigArray);
 -         }
 - 
 -         // Load the config on this directory.
 -         try {
 -             configArray = configArrayFactory.loadInDirectory(directoryPath);
 -         } catch (error) {
 -             /* istanbul ignore next */
 -             if (error.code === "EACCES") {
 -                 debug("Stop traversing because of 'EACCES' error.");
 -                 return this._cacheConfig(directoryPath, baseConfigArray);
 -             }
 -             throw error;
 -         }
 - 
 -         if (configArray.length > 0 && configArray.isRoot()) {
 -             debug("Stop traversing because of 'root:true'.");
 -             configArray.unshift(...baseConfigArray);
 -             return this._cacheConfig(directoryPath, configArray);
 -         }
 - 
 -         // Load from the ancestors and merge it.
 -         const parentPath = path.dirname(directoryPath);
 -         const parentConfigArray = parentPath && parentPath !== directoryPath
 -             ? this._loadConfigInAncestors(
 -                 parentPath,
 -                 configsExistInSubdirs || configArray.length > 0
 -             )
 -             : baseConfigArray;
 - 
 -         if (configArray.length > 0) {
 -             configArray.unshift(...parentConfigArray);
 -         } else {
 -             configArray = parentConfigArray;
 -         }
 - 
 -         // Cache and return.
 -         return this._cacheConfig(directoryPath, configArray);
 -     }
 - 
 -     /**
 -      * Freeze and cache a given config.
 -      * @param {string} directoryPath The path to a directory as a cache key.
 -      * @param {ConfigArray} configArray The config array as a cache value.
 -      * @returns {ConfigArray} The `configArray` (frozen).
 -      */
 -     _cacheConfig(directoryPath, configArray) {
 -         const { configCache } = internalSlotsMap.get(this);
 - 
 -         Object.freeze(configArray);
 -         configCache.set(directoryPath, configArray);
 - 
 -         return configArray;
 -     }
 - 
 -     /**
 -      * Finalize a given config array.
 -      * Concatenate `--config` and other CLI options.
 -      * @param {ConfigArray} configArray The parent config array.
 -      * @param {string} directoryPath The path to the leaf directory to find config files.
 -      * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
 -      * @returns {ConfigArray} The loaded config.
 -      * @private
 -      */
 -     _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
 -         const {
 -             cliConfigArray,
 -             configArrayFactory,
 -             finalizeCache,
 -             useEslintrc,
 -             builtInRules
 -         } = internalSlotsMap.get(this);
 - 
 -         let finalConfigArray = finalizeCache.get(configArray);
 - 
 -         if (!finalConfigArray) {
 -             finalConfigArray = configArray;
 - 
 -             // Load the personal config if there are no regular config files.
 -             if (
 -                 useEslintrc &&
 -                 configArray.every(c => !c.filePath) &&
 -                 cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
 -             ) {
 -                 const homePath = os.homedir();
 - 
 -                 debug("Loading the config file of the home directory:", homePath);
 - 
 -                 const personalConfigArray = configArrayFactory.loadInDirectory(
 -                     homePath,
 -                     { name: "PersonalConfig" }
 -                 );
 - 
 -                 if (
 -                     personalConfigArray.length > 0 &&
 -                     !directoryPath.startsWith(homePath)
 -                 ) {
 -                     const lastElement =
 -                         personalConfigArray[personalConfigArray.length - 1];
 - 
 -                     emitDeprecationWarning(
 -                         lastElement.filePath,
 -                         "ESLINT_PERSONAL_CONFIG_LOAD"
 -                     );
 -                 }
 - 
 -                 finalConfigArray = finalConfigArray.concat(personalConfigArray);
 -             }
 - 
 -             // Apply CLI options.
 -             if (cliConfigArray.length > 0) {
 -                 finalConfigArray = finalConfigArray.concat(cliConfigArray);
 -             }
 - 
 -             // Validate rule settings and environments.
 -             const validator = new ConfigValidator({
 -                 builtInRules
 -             });
 - 
 -             validator.validateConfigArray(finalConfigArray);
 - 
 -             // Cache it.
 -             Object.freeze(finalConfigArray);
 -             finalizeCache.set(configArray, finalConfigArray);
 - 
 -             debug(
 -                 "Configuration was determined: %o on %s",
 -                 finalConfigArray,
 -                 directoryPath
 -             );
 -         }
 - 
 -         // At least one element (the default ignore patterns) exists.
 -         if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
 -             throw new ConfigurationNotFoundError(directoryPath);
 -         }
 - 
 -         return finalConfigArray;
 -     }
 - }
 - 
 - //------------------------------------------------------------------------------
 - // Public Interface
 - //------------------------------------------------------------------------------
 - 
 - export { CascadingConfigArrayFactory };
 
 
  |