update socials section
This commit is contained in:
		
							
								
								
									
										67
									
								
								node_modules/eslint/lib/config/default-config.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								node_modules/eslint/lib/config/default-config.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /** | ||||
|  * @fileoverview Default configuration | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const Rules = require("../rules"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| exports.defaultConfig = [ | ||||
|     { | ||||
|         plugins: { | ||||
|             "@": { | ||||
|  | ||||
|                 /* | ||||
|                  * Because we try to delay loading rules until absolutely | ||||
|                  * necessary, a proxy allows us to hook into the lazy-loading | ||||
|                  * aspect of the rules map while still keeping all of the | ||||
|                  * relevant configuration inside of the config array. | ||||
|                  */ | ||||
|                 rules: new Proxy({}, { | ||||
|                     get(target, property) { | ||||
|                         return Rules.get(property); | ||||
|                     }, | ||||
|  | ||||
|                     has(target, property) { | ||||
|                         return Rules.has(property); | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|         }, | ||||
|         languageOptions: { | ||||
|             sourceType: "module", | ||||
|             ecmaVersion: "latest", | ||||
|             parser: require("espree"), | ||||
|             parserOptions: {} | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     // default ignores are listed here | ||||
|     { | ||||
|         ignores: [ | ||||
|             "**/node_modules/", | ||||
|             ".git/" | ||||
|         ] | ||||
|     }, | ||||
|  | ||||
|     // intentionally empty config to ensure these files are globbed by default | ||||
|     { | ||||
|         files: ["**/*.js", "**/*.mjs"] | ||||
|     }, | ||||
|     { | ||||
|         files: ["**/*.cjs"], | ||||
|         languageOptions: { | ||||
|             sourceType: "commonjs", | ||||
|             ecmaVersion: "latest" | ||||
|         } | ||||
|     } | ||||
| ]; | ||||
							
								
								
									
										380
									
								
								node_modules/eslint/lib/config/flat-config-array.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								node_modules/eslint/lib/config/flat-config-array.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,380 @@ | ||||
| /** | ||||
|  * @fileoverview Flat Config Array | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array"); | ||||
| const { flatConfigSchema } = require("./flat-config-schema"); | ||||
| const { RuleValidator } = require("./rule-validator"); | ||||
| const { defaultConfig } = require("./default-config"); | ||||
| const jsPlugin = require("@eslint/js"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Fields that are considered metadata and not part of the config object. | ||||
|  */ | ||||
| const META_FIELDS = new Set(["name"]); | ||||
|  | ||||
| const ruleValidator = new RuleValidator(); | ||||
|  | ||||
| /** | ||||
|  * Splits a plugin identifier in the form a/b/c into two parts: a/b and c. | ||||
|  * @param {string} identifier The identifier to parse. | ||||
|  * @returns {{objectName: string, pluginName: string}} The parts of the plugin | ||||
|  *      name. | ||||
|  */ | ||||
| function splitPluginIdentifier(identifier) { | ||||
|     const parts = identifier.split("/"); | ||||
|  | ||||
|     return { | ||||
|         objectName: parts.pop(), | ||||
|         pluginName: parts.join("/") | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the name of an object in the config by reading its `meta` key. | ||||
|  * @param {Object} object The object to check. | ||||
|  * @returns {string?} The name of the object if found or `null` if there | ||||
|  *      is no name. | ||||
|  */ | ||||
| function getObjectId(object) { | ||||
|  | ||||
|     // first check old-style name | ||||
|     let name = object.name; | ||||
|  | ||||
|     if (!name) { | ||||
|  | ||||
|         if (!object.meta) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         name = object.meta.name; | ||||
|  | ||||
|         if (!name) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // now check for old-style version | ||||
|     let version = object.version; | ||||
|  | ||||
|     if (!version) { | ||||
|         version = object.meta && object.meta.version; | ||||
|     } | ||||
|  | ||||
|     // if there's a version then append that | ||||
|     if (version) { | ||||
|         return `${name}@${version}`; | ||||
|     } | ||||
|  | ||||
|     return name; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Wraps a config error with details about where the error occurred. | ||||
|  * @param {Error} error The original error. | ||||
|  * @param {number} originalLength The original length of the config array. | ||||
|  * @param {number} baseLength The length of the base config. | ||||
|  * @returns {TypeError} The new error with details. | ||||
|  */ | ||||
| function wrapConfigErrorWithDetails(error, originalLength, baseLength) { | ||||
|  | ||||
|     let location = "user-defined"; | ||||
|     let configIndex = error.index; | ||||
|  | ||||
|     /* | ||||
|      * A config array is set up in this order: | ||||
|      * 1. Base config | ||||
|      * 2. Original configs | ||||
|      * 3. User-defined configs | ||||
|      * 4. CLI-defined configs | ||||
|      * | ||||
|      * So we need to adjust the index to account for the base config. | ||||
|      * | ||||
|      * - If the index is less than the base length, it's in the base config | ||||
|      *   (as specified by `baseConfig` argument to `FlatConfigArray` constructor). | ||||
|      * - If the index is greater than the base length but less than the original | ||||
|      *   length + base length, it's in the original config. The original config | ||||
|      *   is passed to the `FlatConfigArray` constructor as the first argument. | ||||
|      * - Otherwise, it's in the user-defined config, which is loaded from the | ||||
|      *   config file and merged with any command-line options. | ||||
|      */ | ||||
|     if (error.index < baseLength) { | ||||
|         location = "base"; | ||||
|     } else if (error.index < originalLength + baseLength) { | ||||
|         location = "original"; | ||||
|         configIndex = error.index - baseLength; | ||||
|     } else { | ||||
|         configIndex = error.index - originalLength - baseLength; | ||||
|     } | ||||
|  | ||||
|     return new TypeError( | ||||
|         `${error.message.slice(0, -1)} at ${location} index ${configIndex}.`, | ||||
|         { cause: error } | ||||
|     ); | ||||
| } | ||||
|  | ||||
| const originalBaseConfig = Symbol("originalBaseConfig"); | ||||
| const originalLength = Symbol("originalLength"); | ||||
| const baseLength = Symbol("baseLength"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Represents an array containing configuration information for ESLint. | ||||
|  */ | ||||
| class FlatConfigArray extends ConfigArray { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {*[]} configs An array of configuration information. | ||||
|      * @param {{basePath: string, shouldIgnore: boolean, baseConfig: FlatConfig}} options The options | ||||
|      *      to use for the config array instance. | ||||
|      */ | ||||
|     constructor(configs, { | ||||
|         basePath, | ||||
|         shouldIgnore = true, | ||||
|         baseConfig = defaultConfig | ||||
|     } = {}) { | ||||
|         super(configs, { | ||||
|             basePath, | ||||
|             schema: flatConfigSchema | ||||
|         }); | ||||
|  | ||||
|         /** | ||||
|          * The original length of the array before any modifications. | ||||
|          * @type {number} | ||||
|          */ | ||||
|         this[originalLength] = this.length; | ||||
|  | ||||
|         if (baseConfig[Symbol.iterator]) { | ||||
|             this.unshift(...baseConfig); | ||||
|         } else { | ||||
|             this.unshift(baseConfig); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * The length of the array after applying the base config. | ||||
|          * @type {number} | ||||
|          */ | ||||
|         this[baseLength] = this.length - this[originalLength]; | ||||
|  | ||||
|         /** | ||||
|          * The base config used to build the config array. | ||||
|          * @type {Array<FlatConfig>} | ||||
|          */ | ||||
|         this[originalBaseConfig] = baseConfig; | ||||
|         Object.defineProperty(this, originalBaseConfig, { writable: false }); | ||||
|  | ||||
|         /** | ||||
|          * Determines if `ignores` fields should be honored. | ||||
|          * If true, then all `ignores` fields are honored. | ||||
|          * if false, then only `ignores` fields in the baseConfig are honored. | ||||
|          * @type {boolean} | ||||
|          */ | ||||
|         this.shouldIgnore = shouldIgnore; | ||||
|         Object.defineProperty(this, "shouldIgnore", { writable: false }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Normalizes the array by calling the superclass method and catching/rethrowing | ||||
|      * any ConfigError exceptions with additional details. | ||||
|      * @param {any} [context] The context to use to normalize the array. | ||||
|      * @returns {Promise<FlatConfigArray>} A promise that resolves when the array is normalized. | ||||
|      */ | ||||
|     normalize(context) { | ||||
|         return super.normalize(context) | ||||
|             .catch(error => { | ||||
|                 if (error.name === "ConfigError") { | ||||
|                     throw wrapConfigErrorWithDetails(error, this[originalLength], this[baseLength]); | ||||
|                 } | ||||
|  | ||||
|                 throw error; | ||||
|  | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Normalizes the array by calling the superclass method and catching/rethrowing | ||||
|      * any ConfigError exceptions with additional details. | ||||
|      * @param {any} [context] The context to use to normalize the array. | ||||
|      * @returns {FlatConfigArray} The current instance. | ||||
|      * @throws {TypeError} If the config is invalid. | ||||
|      */ | ||||
|     normalizeSync(context) { | ||||
|  | ||||
|         try { | ||||
|  | ||||
|             return super.normalizeSync(context); | ||||
|  | ||||
|         } catch (error) { | ||||
|  | ||||
|             if (error.name === "ConfigError") { | ||||
|                 throw wrapConfigErrorWithDetails(error, this[originalLength], this[baseLength]); | ||||
|             } | ||||
|  | ||||
|             throw error; | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /* eslint-disable class-methods-use-this -- Desired as instance method */ | ||||
|     /** | ||||
|      * Replaces a config with another config to allow us to put strings | ||||
|      * in the config array that will be replaced by objects before | ||||
|      * normalization. | ||||
|      * @param {Object} config The config to preprocess. | ||||
|      * @returns {Object} The preprocessed config. | ||||
|      */ | ||||
|     [ConfigArraySymbol.preprocessConfig](config) { | ||||
|         if (config === "eslint:recommended") { | ||||
|  | ||||
|             // if we are in a Node.js environment warn the user | ||||
|             if (typeof process !== "undefined" && process.emitWarning) { | ||||
|                 process.emitWarning("The 'eslint:recommended' string configuration is deprecated and will be replaced by the @eslint/js package's 'recommended' config."); | ||||
|             } | ||||
|  | ||||
|             return jsPlugin.configs.recommended; | ||||
|         } | ||||
|  | ||||
|         if (config === "eslint:all") { | ||||
|  | ||||
|             // if we are in a Node.js environment warn the user | ||||
|             if (typeof process !== "undefined" && process.emitWarning) { | ||||
|                 process.emitWarning("The 'eslint:all' string configuration is deprecated and will be replaced by the @eslint/js package's 'all' config."); | ||||
|             } | ||||
|  | ||||
|             return jsPlugin.configs.all; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * If a config object has `ignores` and no other non-meta fields, then it's an object | ||||
|          * for global ignores. If `shouldIgnore` is false, that object shouldn't apply, | ||||
|          * so we'll remove its `ignores`. | ||||
|          */ | ||||
|         if ( | ||||
|             !this.shouldIgnore && | ||||
|             !this[originalBaseConfig].includes(config) && | ||||
|             config.ignores && | ||||
|             Object.keys(config).filter(key => !META_FIELDS.has(key)).length === 1 | ||||
|         ) { | ||||
|             /* eslint-disable-next-line no-unused-vars -- need to strip off other keys */ | ||||
|             const { ignores, ...otherKeys } = config; | ||||
|  | ||||
|             return otherKeys; | ||||
|         } | ||||
|  | ||||
|         return config; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Finalizes the config by replacing plugin references with their objects | ||||
|      * and validating rule option schemas. | ||||
|      * @param {Object} config The config to finalize. | ||||
|      * @returns {Object} The finalized config. | ||||
|      * @throws {TypeError} If the config is invalid. | ||||
|      */ | ||||
|     [ConfigArraySymbol.finalizeConfig](config) { | ||||
|  | ||||
|         const { plugins, languageOptions, processor } = config; | ||||
|         let parserName, processorName; | ||||
|         let invalidParser = false, | ||||
|             invalidProcessor = false; | ||||
|  | ||||
|         // Check parser value | ||||
|         if (languageOptions && languageOptions.parser) { | ||||
|             const { parser } = languageOptions; | ||||
|  | ||||
|             if (typeof parser === "object") { | ||||
|                 parserName = getObjectId(parser); | ||||
|  | ||||
|                 if (!parserName) { | ||||
|                     invalidParser = true; | ||||
|                 } | ||||
|  | ||||
|             } else { | ||||
|                 invalidParser = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Check processor value | ||||
|         if (processor) { | ||||
|             if (typeof processor === "string") { | ||||
|                 const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor); | ||||
|  | ||||
|                 processorName = processor; | ||||
|  | ||||
|                 if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) { | ||||
|                     throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`); | ||||
|                 } | ||||
|  | ||||
|                 config.processor = plugins[pluginName].processors[localProcessorName]; | ||||
|             } else if (typeof processor === "object") { | ||||
|                 processorName = getObjectId(processor); | ||||
|  | ||||
|                 if (!processorName) { | ||||
|                     invalidProcessor = true; | ||||
|                 } | ||||
|  | ||||
|             } else { | ||||
|                 invalidProcessor = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         ruleValidator.validate(config); | ||||
|  | ||||
|         // apply special logic for serialization into JSON | ||||
|         /* eslint-disable object-shorthand -- shorthand would change "this" value */ | ||||
|         Object.defineProperty(config, "toJSON", { | ||||
|             value: function() { | ||||
|  | ||||
|                 if (invalidParser) { | ||||
|                     throw new Error("Could not serialize parser object (missing 'meta' object)."); | ||||
|                 } | ||||
|  | ||||
|                 if (invalidProcessor) { | ||||
|                     throw new Error("Could not serialize processor object (missing 'meta' object)."); | ||||
|                 } | ||||
|  | ||||
|                 return { | ||||
|                     ...this, | ||||
|                     plugins: Object.entries(plugins).map(([namespace, plugin]) => { | ||||
|  | ||||
|                         const pluginId = getObjectId(plugin); | ||||
|  | ||||
|                         if (!pluginId) { | ||||
|                             return namespace; | ||||
|                         } | ||||
|  | ||||
|                         return `${namespace}:${pluginId}`; | ||||
|                     }), | ||||
|                     languageOptions: { | ||||
|                         ...languageOptions, | ||||
|                         parser: parserName | ||||
|                     }, | ||||
|                     processor: processorName | ||||
|                 }; | ||||
|             } | ||||
|         }); | ||||
|         /* eslint-enable object-shorthand -- ok to enable now */ | ||||
|  | ||||
|         return config; | ||||
|     } | ||||
|     /* eslint-enable class-methods-use-this -- Desired as instance method */ | ||||
|  | ||||
| } | ||||
|  | ||||
| exports.FlatConfigArray = FlatConfigArray; | ||||
							
								
								
									
										111
									
								
								node_modules/eslint/lib/config/flat-config-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								node_modules/eslint/lib/config/flat-config-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| /** | ||||
|  * @fileoverview Shared functions to work with configs. | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Functions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Parses a ruleId into its plugin and rule parts. | ||||
|  * @param {string} ruleId The rule ID to parse. | ||||
|  * @returns {{pluginName:string,ruleName:string}} The plugin and rule | ||||
|  *      parts of the ruleId; | ||||
|  */ | ||||
| function parseRuleId(ruleId) { | ||||
|     let pluginName, ruleName; | ||||
|  | ||||
|     // distinguish between core rules and plugin rules | ||||
|     if (ruleId.includes("/")) { | ||||
|  | ||||
|         // mimic scoped npm packages | ||||
|         if (ruleId.startsWith("@")) { | ||||
|             pluginName = ruleId.slice(0, ruleId.lastIndexOf("/")); | ||||
|         } else { | ||||
|             pluginName = ruleId.slice(0, ruleId.indexOf("/")); | ||||
|         } | ||||
|  | ||||
|         ruleName = ruleId.slice(pluginName.length + 1); | ||||
|     } else { | ||||
|         pluginName = "@"; | ||||
|         ruleName = ruleId; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         pluginName, | ||||
|         ruleName | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Retrieves a rule instance from a given config based on the ruleId. | ||||
|  * @param {string} ruleId The rule ID to look for. | ||||
|  * @param {FlatConfig} config The config to search. | ||||
|  * @returns {import("../shared/types").Rule|undefined} The rule if found | ||||
|  *      or undefined if not. | ||||
|  */ | ||||
| function getRuleFromConfig(ruleId, config) { | ||||
|  | ||||
|     const { pluginName, ruleName } = parseRuleId(ruleId); | ||||
|  | ||||
|     const plugin = config.plugins && config.plugins[pluginName]; | ||||
|     let rule = plugin && plugin.rules && plugin.rules[ruleName]; | ||||
|  | ||||
|  | ||||
|     // normalize function rules into objects | ||||
|     if (rule && typeof rule === "function") { | ||||
|         rule = { | ||||
|             create: rule | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return rule; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets a complete options schema for a rule. | ||||
|  * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object | ||||
|  * @returns {Object} JSON Schema for the rule's options. | ||||
|  */ | ||||
| function getRuleOptionsSchema(rule) { | ||||
|  | ||||
|     if (!rule) { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     const schema = rule.schema || rule.meta && rule.meta.schema; | ||||
|  | ||||
|     if (Array.isArray(schema)) { | ||||
|         if (schema.length) { | ||||
|             return { | ||||
|                 type: "array", | ||||
|                 items: schema, | ||||
|                 minItems: 0, | ||||
|                 maxItems: schema.length | ||||
|             }; | ||||
|         } | ||||
|         return { | ||||
|             type: "array", | ||||
|             minItems: 0, | ||||
|             maxItems: 0 | ||||
|         }; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     // Given a full schema, leave it alone | ||||
|     return schema || null; | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| module.exports = { | ||||
|     parseRuleId, | ||||
|     getRuleFromConfig, | ||||
|     getRuleOptionsSchema | ||||
| }; | ||||
							
								
								
									
										598
									
								
								node_modules/eslint/lib/config/flat-config-schema.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										598
									
								
								node_modules/eslint/lib/config/flat-config-schema.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,598 @@ | ||||
| /** | ||||
|  * @fileoverview Flat config schema | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /* | ||||
|  * Note: This can be removed in ESLint v9 because structuredClone is available globally | ||||
|  * starting in Node.js v17. | ||||
|  */ | ||||
| const structuredClone = require("@ungap/structured-clone").default; | ||||
| const { normalizeSeverityToNumber } = require("../shared/severity"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Type Definitions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * @typedef ObjectPropertySchema | ||||
|  * @property {Function|string} merge The function or name of the function to call | ||||
|  *      to merge multiple objects with this property. | ||||
|  * @property {Function|string} validate The function or name of the function to call | ||||
|  *      to validate the value of this property. | ||||
|  */ | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const ruleSeverities = new Map([ | ||||
|     [0, 0], ["off", 0], | ||||
|     [1, 1], ["warn", 1], | ||||
|     [2, 2], ["error", 2] | ||||
| ]); | ||||
|  | ||||
| const globalVariablesValues = new Set([ | ||||
|     true, "true", "writable", "writeable", | ||||
|     false, "false", "readonly", "readable", null, | ||||
|     "off" | ||||
| ]); | ||||
|  | ||||
| /** | ||||
|  * Check if a value is a non-null object. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {boolean} `true` if the value is a non-null object. | ||||
|  */ | ||||
| function isNonNullObject(value) { | ||||
|     return typeof value === "object" && value !== null; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a value is a non-null non-array object. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {boolean} `true` if the value is a non-null non-array object. | ||||
|  */ | ||||
| function isNonArrayObject(value) { | ||||
|     return isNonNullObject(value) && !Array.isArray(value); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a value is undefined. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {boolean} `true` if the value is undefined. | ||||
|  */ | ||||
| function isUndefined(value) { | ||||
|     return typeof value === "undefined"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Deeply merges two non-array objects. | ||||
|  * @param {Object} first The base object. | ||||
|  * @param {Object} second The overrides object. | ||||
|  * @param {Map<string, Map<string, Object>>} [mergeMap] Maps the combination of first and second arguments to a merged result. | ||||
|  * @returns {Object} An object with properties from both first and second. | ||||
|  */ | ||||
| function deepMerge(first, second, mergeMap = new Map()) { | ||||
|  | ||||
|     let secondMergeMap = mergeMap.get(first); | ||||
|  | ||||
|     if (secondMergeMap) { | ||||
|         const result = secondMergeMap.get(second); | ||||
|  | ||||
|         if (result) { | ||||
|  | ||||
|             // If this combination of first and second arguments has been already visited, return the previously created result. | ||||
|             return result; | ||||
|         } | ||||
|     } else { | ||||
|         secondMergeMap = new Map(); | ||||
|         mergeMap.set(first, secondMergeMap); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * First create a result object where properties from the second object | ||||
|      * overwrite properties from the first. This sets up a baseline to use | ||||
|      * later rather than needing to inspect and change every property | ||||
|      * individually. | ||||
|      */ | ||||
|     const result = { | ||||
|         ...first, | ||||
|         ...second | ||||
|     }; | ||||
|  | ||||
|     delete result.__proto__; // eslint-disable-line no-proto -- don't merge own property "__proto__" | ||||
|  | ||||
|     // Store the pending result for this combination of first and second arguments. | ||||
|     secondMergeMap.set(second, result); | ||||
|  | ||||
|     for (const key of Object.keys(second)) { | ||||
|  | ||||
|         // avoid hairy edge case | ||||
|         if (key === "__proto__" || !Object.prototype.propertyIsEnumerable.call(first, key)) { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         const firstValue = first[key]; | ||||
|         const secondValue = second[key]; | ||||
|  | ||||
|         if (isNonArrayObject(firstValue) && isNonArrayObject(secondValue)) { | ||||
|             result[key] = deepMerge(firstValue, secondValue, mergeMap); | ||||
|         } else if (isUndefined(secondValue)) { | ||||
|             result[key] = firstValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return result; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Normalizes the rule options config for a given rule by ensuring that | ||||
|  * it is an array and that the first item is 0, 1, or 2. | ||||
|  * @param {Array|string|number} ruleOptions The rule options config. | ||||
|  * @returns {Array} An array of rule options. | ||||
|  */ | ||||
| function normalizeRuleOptions(ruleOptions) { | ||||
|  | ||||
|     const finalOptions = Array.isArray(ruleOptions) | ||||
|         ? ruleOptions.slice(0) | ||||
|         : [ruleOptions]; | ||||
|  | ||||
|     finalOptions[0] = ruleSeverities.get(finalOptions[0]); | ||||
|     return structuredClone(finalOptions); | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Assertions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * The error type when a rule's options are configured with an invalid type. | ||||
|  */ | ||||
| class InvalidRuleOptionsError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} ruleId Rule name being configured. | ||||
|      * @param {any} value The invalid value. | ||||
|      */ | ||||
|     constructor(ruleId, value) { | ||||
|         super(`Key "${ruleId}": Expected severity of "off", 0, "warn", 1, "error", or 2.`); | ||||
|         this.messageTemplate = "invalid-rule-options"; | ||||
|         this.messageData = { ruleId, value }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a value is a valid rule options entry. | ||||
|  * @param {string} ruleId Rule name being configured. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {void} | ||||
|  * @throws {InvalidRuleOptionsError} If the value isn't a valid rule options. | ||||
|  */ | ||||
| function assertIsRuleOptions(ruleId, value) { | ||||
|     if (typeof value !== "string" && typeof value !== "number" && !Array.isArray(value)) { | ||||
|         throw new InvalidRuleOptionsError(ruleId, value); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when a rule's severity is invalid. | ||||
|  */ | ||||
| class InvalidRuleSeverityError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} ruleId Rule name being configured. | ||||
|      * @param {any} value The invalid value. | ||||
|      */ | ||||
|     constructor(ruleId, value) { | ||||
|         super(`Key "${ruleId}": Expected severity of "off", 0, "warn", 1, "error", or 2.`); | ||||
|         this.messageTemplate = "invalid-rule-severity"; | ||||
|         this.messageData = { ruleId, value }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a value is valid rule severity. | ||||
|  * @param {string} ruleId Rule name being configured. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {void} | ||||
|  * @throws {InvalidRuleSeverityError} If the value isn't a valid rule severity. | ||||
|  */ | ||||
| function assertIsRuleSeverity(ruleId, value) { | ||||
|     const severity = ruleSeverities.get(value); | ||||
|  | ||||
|     if (typeof severity === "undefined") { | ||||
|         throw new InvalidRuleSeverityError(ruleId, value); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a given string is the form pluginName/objectName. | ||||
|  * @param {string} value The string to check. | ||||
|  * @returns {void} | ||||
|  * @throws {TypeError} If the string isn't in the correct format. | ||||
|  */ | ||||
| function assertIsPluginMemberName(value) { | ||||
|     if (!/[@a-z0-9-_$]+(?:\/(?:[a-z0-9-_$]+))+$/iu.test(value)) { | ||||
|         throw new TypeError(`Expected string in the form "pluginName/objectName" but found "${value}".`); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a value is an object. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {void} | ||||
|  * @throws {TypeError} If the value isn't an object. | ||||
|  */ | ||||
| function assertIsObject(value) { | ||||
|     if (!isNonNullObject(value)) { | ||||
|         throw new TypeError("Expected an object."); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when there's an eslintrc-style options in a flat config. | ||||
|  */ | ||||
| class IncompatibleKeyError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} key The invalid key. | ||||
|      */ | ||||
|     constructor(key) { | ||||
|         super("This appears to be in eslintrc format rather than flat config format."); | ||||
|         this.messageTemplate = "eslintrc-incompat"; | ||||
|         this.messageData = { key }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when there's an eslintrc-style plugins array found. | ||||
|  */ | ||||
| class IncompatiblePluginsError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {Array<string>} plugins The plugins array. | ||||
|      */ | ||||
|     constructor(plugins) { | ||||
|         super("This appears to be in eslintrc format (array of strings) rather than flat config format (object)."); | ||||
|         this.messageTemplate = "eslintrc-plugins"; | ||||
|         this.messageData = { plugins }; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Low-Level Schemas | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const booleanSchema = { | ||||
|     merge: "replace", | ||||
|     validate: "boolean" | ||||
| }; | ||||
|  | ||||
| const ALLOWED_SEVERITIES = new Set(["error", "warn", "off", 2, 1, 0]); | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const disableDirectiveSeveritySchema = { | ||||
|     merge(first, second) { | ||||
|         const value = second === void 0 ? first : second; | ||||
|  | ||||
|         if (typeof value === "boolean") { | ||||
|             return value ? "warn" : "off"; | ||||
|         } | ||||
|  | ||||
|         return normalizeSeverityToNumber(value); | ||||
|     }, | ||||
|     validate(value) { | ||||
|         if (!(ALLOWED_SEVERITIES.has(value) || typeof value === "boolean")) { | ||||
|             throw new TypeError("Expected one of: \"error\", \"warn\", \"off\", 0, 1, 2, or a boolean."); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const deepObjectAssignSchema = { | ||||
|     merge(first = {}, second = {}) { | ||||
|         return deepMerge(first, second); | ||||
|     }, | ||||
|     validate: "object" | ||||
| }; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // High-Level Schemas | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const globalsSchema = { | ||||
|     merge: "assign", | ||||
|     validate(value) { | ||||
|  | ||||
|         assertIsObject(value); | ||||
|  | ||||
|         for (const key of Object.keys(value)) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (key === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (key !== key.trim()) { | ||||
|                 throw new TypeError(`Global "${key}" has leading or trailing whitespace.`); | ||||
|             } | ||||
|  | ||||
|             if (!globalVariablesValues.has(value[key])) { | ||||
|                 throw new TypeError(`Key "${key}": Expected "readonly", "writable", or "off".`); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const parserSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|  | ||||
|         if (!value || typeof value !== "object" || | ||||
|             (typeof value.parse !== "function" && typeof value.parseForESLint !== "function") | ||||
|         ) { | ||||
|             throw new TypeError("Expected object with parse() or parseForESLint() method."); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const pluginsSchema = { | ||||
|     merge(first = {}, second = {}) { | ||||
|         const keys = new Set([...Object.keys(first), ...Object.keys(second)]); | ||||
|         const result = {}; | ||||
|  | ||||
|         // manually validate that plugins are not redefined | ||||
|         for (const key of keys) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (key === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (key in first && key in second && first[key] !== second[key]) { | ||||
|                 throw new TypeError(`Cannot redefine plugin "${key}".`); | ||||
|             } | ||||
|  | ||||
|             result[key] = second[key] || first[key]; | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     }, | ||||
|     validate(value) { | ||||
|  | ||||
|         // first check the value to be sure it's an object | ||||
|         if (value === null || typeof value !== "object") { | ||||
|             throw new TypeError("Expected an object."); | ||||
|         } | ||||
|  | ||||
|         // make sure it's not an array, which would mean eslintrc-style is used | ||||
|         if (Array.isArray(value)) { | ||||
|             throw new IncompatiblePluginsError(value); | ||||
|         } | ||||
|  | ||||
|         // second check the keys to make sure they are objects | ||||
|         for (const key of Object.keys(value)) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (key === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (value[key] === null || typeof value[key] !== "object") { | ||||
|                 throw new TypeError(`Key "${key}": Expected an object.`); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const processorSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|         if (typeof value === "string") { | ||||
|             assertIsPluginMemberName(value); | ||||
|         } else if (value && typeof value === "object") { | ||||
|             if (typeof value.preprocess !== "function" || typeof value.postprocess !== "function") { | ||||
|                 throw new TypeError("Object must have a preprocess() and a postprocess() method."); | ||||
|             } | ||||
|         } else { | ||||
|             throw new TypeError("Expected an object or a string."); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const rulesSchema = { | ||||
|     merge(first = {}, second = {}) { | ||||
|  | ||||
|         const result = { | ||||
|             ...first, | ||||
|             ...second | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         for (const ruleId of Object.keys(result)) { | ||||
|  | ||||
|             try { | ||||
|  | ||||
|                 // avoid hairy edge case | ||||
|                 if (ruleId === "__proto__") { | ||||
|  | ||||
|                     /* eslint-disable-next-line no-proto -- Though deprecated, may still be present */ | ||||
|                     delete result.__proto__; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 result[ruleId] = normalizeRuleOptions(result[ruleId]); | ||||
|  | ||||
|                 /* | ||||
|                  * If either rule config is missing, then the correct | ||||
|                  * config is already present and we just need to normalize | ||||
|                  * the severity. | ||||
|                  */ | ||||
|                 if (!(ruleId in first) || !(ruleId in second)) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 const firstRuleOptions = normalizeRuleOptions(first[ruleId]); | ||||
|                 const secondRuleOptions = normalizeRuleOptions(second[ruleId]); | ||||
|  | ||||
|                 /* | ||||
|                  * If the second rule config only has a severity (length of 1), | ||||
|                  * then use that severity and keep the rest of the options from | ||||
|                  * the first rule config. | ||||
|                  */ | ||||
|                 if (secondRuleOptions.length === 1) { | ||||
|                     result[ruleId] = [secondRuleOptions[0], ...firstRuleOptions.slice(1)]; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * In any other situation, then the second rule config takes | ||||
|                  * precedence. That means the value at `result[ruleId]` is | ||||
|                  * already correct and no further work is necessary. | ||||
|                  */ | ||||
|             } catch (ex) { | ||||
|                 throw new Error(`Key "${ruleId}": ${ex.message}`, { cause: ex }); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|  | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     validate(value) { | ||||
|         assertIsObject(value); | ||||
|  | ||||
|         /* | ||||
|          * We are not checking the rule schema here because there is no | ||||
|          * guarantee that the rule definition is present at this point. Instead | ||||
|          * we wait and check the rule schema during the finalization step | ||||
|          * of calculating a config. | ||||
|          */ | ||||
|         for (const ruleId of Object.keys(value)) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (ruleId === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             const ruleOptions = value[ruleId]; | ||||
|  | ||||
|             assertIsRuleOptions(ruleId, ruleOptions); | ||||
|  | ||||
|             if (Array.isArray(ruleOptions)) { | ||||
|                 assertIsRuleSeverity(ruleId, ruleOptions[0]); | ||||
|             } else { | ||||
|                 assertIsRuleSeverity(ruleId, ruleOptions); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const ecmaVersionSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|         if (typeof value === "number" || value === "latest") { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         throw new TypeError("Expected a number or \"latest\"."); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const sourceTypeSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|         if (typeof value !== "string" || !/^(?:script|module|commonjs)$/u.test(value)) { | ||||
|             throw new TypeError("Expected \"script\", \"module\", or \"commonjs\"."); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Creates a schema that always throws an error. Useful for warning | ||||
|  * about eslintrc-style keys. | ||||
|  * @param {string} key The eslintrc key to create a schema for. | ||||
|  * @returns {ObjectPropertySchema} The schema. | ||||
|  */ | ||||
| function createEslintrcErrorSchema(key) { | ||||
|     return { | ||||
|         merge: "replace", | ||||
|         validate() { | ||||
|             throw new IncompatibleKeyError(key); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| const eslintrcKeys = [ | ||||
|     "env", | ||||
|     "extends", | ||||
|     "globals", | ||||
|     "ignorePatterns", | ||||
|     "noInlineConfig", | ||||
|     "overrides", | ||||
|     "parser", | ||||
|     "parserOptions", | ||||
|     "reportUnusedDisableDirectives", | ||||
|     "root" | ||||
| ]; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Full schema | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const flatConfigSchema = { | ||||
|  | ||||
|     // eslintrc-style keys that should always error | ||||
|     ...Object.fromEntries(eslintrcKeys.map(key => [key, createEslintrcErrorSchema(key)])), | ||||
|  | ||||
|     // flat config keys | ||||
|     settings: deepObjectAssignSchema, | ||||
|     linterOptions: { | ||||
|         schema: { | ||||
|             noInlineConfig: booleanSchema, | ||||
|             reportUnusedDisableDirectives: disableDirectiveSeveritySchema | ||||
|         } | ||||
|     }, | ||||
|     languageOptions: { | ||||
|         schema: { | ||||
|             ecmaVersion: ecmaVersionSchema, | ||||
|             sourceType: sourceTypeSchema, | ||||
|             globals: globalsSchema, | ||||
|             parser: parserSchema, | ||||
|             parserOptions: deepObjectAssignSchema | ||||
|         } | ||||
|     }, | ||||
|     processor: processorSchema, | ||||
|     plugins: pluginsSchema, | ||||
|     rules: rulesSchema | ||||
| }; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| module.exports = { | ||||
|     flatConfigSchema, | ||||
|     assertIsRuleSeverity, | ||||
|     assertIsRuleOptions | ||||
| }; | ||||
							
								
								
									
										158
									
								
								node_modules/eslint/lib/config/rule-validator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								node_modules/eslint/lib/config/rule-validator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | ||||
| /** | ||||
|  * @fileoverview Rule Validator | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const ajvImport = require("../shared/ajv"); | ||||
| const ajv = ajvImport(); | ||||
| const { | ||||
|     parseRuleId, | ||||
|     getRuleFromConfig, | ||||
|     getRuleOptionsSchema | ||||
| } = require("./flat-config-helpers"); | ||||
| const ruleReplacements = require("../../conf/replacements.json"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Throws a helpful error when a rule cannot be found. | ||||
|  * @param {Object} ruleId The rule identifier. | ||||
|  * @param {string} ruleId.pluginName The ID of the rule to find. | ||||
|  * @param {string} ruleId.ruleName The ID of the rule to find. | ||||
|  * @param {Object} config The config to search in. | ||||
|  * @throws {TypeError} For missing plugin or rule. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function throwRuleNotFoundError({ pluginName, ruleName }, config) { | ||||
|  | ||||
|     const ruleId = pluginName === "@" ? ruleName : `${pluginName}/${ruleName}`; | ||||
|  | ||||
|     const errorMessageHeader = `Key "rules": Key "${ruleId}"`; | ||||
|     let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}".`; | ||||
|  | ||||
|     // if the plugin exists then we need to check if the rule exists | ||||
|     if (config.plugins && config.plugins[pluginName]) { | ||||
|         const replacementRuleName = ruleReplacements.rules[ruleName]; | ||||
|  | ||||
|         if (pluginName === "@" && replacementRuleName) { | ||||
|  | ||||
|             errorMessage = `${errorMessageHeader}: Rule "${ruleName}" was removed and replaced by "${replacementRuleName}".`; | ||||
|  | ||||
|         } else { | ||||
|  | ||||
|             errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`; | ||||
|  | ||||
|             // otherwise, let's see if we can find the rule name elsewhere | ||||
|             for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) { | ||||
|                 if (otherPlugin.rules && otherPlugin.rules[ruleName]) { | ||||
|                     errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // falls through to throw error | ||||
|     } | ||||
|  | ||||
|     throw new TypeError(errorMessage); | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Implements validation functionality for the rules portion of a config. | ||||
|  */ | ||||
| class RuleValidator { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      */ | ||||
|     constructor() { | ||||
|  | ||||
|         /** | ||||
|          * A collection of compiled validators for rules that have already | ||||
|          * been validated. | ||||
|          * @type {WeakMap} | ||||
|          */ | ||||
|         this.validators = new WeakMap(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Validates all of the rule configurations in a config against each | ||||
|      * rule's schema. | ||||
|      * @param {Object} config The full config to validate. This object must | ||||
|      *      contain both the rules section and the plugins section. | ||||
|      * @returns {void} | ||||
|      * @throws {Error} If a rule's configuration does not match its schema. | ||||
|      */ | ||||
|     validate(config) { | ||||
|  | ||||
|         if (!config.rules) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         for (const [ruleId, ruleOptions] of Object.entries(config.rules)) { | ||||
|  | ||||
|             // check for edge case | ||||
|             if (ruleId === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * If a rule is disabled, we don't do any validation. This allows | ||||
|              * users to safely set any value to 0 or "off" without worrying | ||||
|              * that it will cause a validation error. | ||||
|              * | ||||
|              * Note: ruleOptions is always an array at this point because | ||||
|              * this validation occurs after FlatConfigArray has merged and | ||||
|              * normalized values. | ||||
|              */ | ||||
|             if (ruleOptions[0] === 0) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             const rule = getRuleFromConfig(ruleId, config); | ||||
|  | ||||
|             if (!rule) { | ||||
|                 throwRuleNotFoundError(parseRuleId(ruleId), config); | ||||
|             } | ||||
|  | ||||
|             // Precompile and cache validator the first time | ||||
|             if (!this.validators.has(rule)) { | ||||
|                 const schema = getRuleOptionsSchema(rule); | ||||
|  | ||||
|                 if (schema) { | ||||
|                     this.validators.set(rule, ajv.compile(schema)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             const validateRule = this.validators.get(rule); | ||||
|  | ||||
|             if (validateRule) { | ||||
|  | ||||
|                 validateRule(ruleOptions.slice(1)); | ||||
|  | ||||
|                 if (validateRule.errors) { | ||||
|                     throw new Error(`Key "rules": Key "${ruleId}": ${ | ||||
|                         validateRule.errors.map( | ||||
|                             error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n` | ||||
|                         ).join("") | ||||
|                     }`); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| exports.RuleValidator = RuleValidator; | ||||
		Reference in New Issue
	
	Block a user