flat-config-array.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * @fileoverview Flat Config Array
  3. * @author Nicholas C. Zakas
  4. */
  5. "use strict";
  6. //-----------------------------------------------------------------------------
  7. // Requirements
  8. //-----------------------------------------------------------------------------
  9. const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array");
  10. const { flatConfigSchema } = require("./flat-config-schema");
  11. const { RuleValidator } = require("./rule-validator");
  12. const { defaultConfig } = require("./default-config");
  13. const recommendedConfig = require("../../conf/eslint-recommended");
  14. //-----------------------------------------------------------------------------
  15. // Helpers
  16. //-----------------------------------------------------------------------------
  17. const ruleValidator = new RuleValidator();
  18. /**
  19. * Splits a plugin identifier in the form a/b/c into two parts: a/b and c.
  20. * @param {string} identifier The identifier to parse.
  21. * @returns {{objectName: string, pluginName: string}} The parts of the plugin
  22. * name.
  23. */
  24. function splitPluginIdentifier(identifier) {
  25. const parts = identifier.split("/");
  26. return {
  27. objectName: parts.pop(),
  28. pluginName: parts.join("/")
  29. };
  30. }
  31. //-----------------------------------------------------------------------------
  32. // Exports
  33. //-----------------------------------------------------------------------------
  34. /**
  35. * Represents an array containing configuration information for ESLint.
  36. */
  37. class FlatConfigArray extends ConfigArray {
  38. /**
  39. * Creates a new instance.
  40. * @param {*[]} configs An array of configuration information.
  41. * @param {{basePath: string, baseConfig: FlatConfig}} options The options
  42. * to use for the config array instance.
  43. */
  44. constructor(configs, { basePath, baseConfig = defaultConfig } = {}) {
  45. super(configs, {
  46. basePath,
  47. schema: flatConfigSchema
  48. });
  49. if (baseConfig[Symbol.iterator]) {
  50. this.unshift(...baseConfig);
  51. } else {
  52. this.unshift(baseConfig);
  53. }
  54. }
  55. /* eslint-disable class-methods-use-this -- Desired as instance method */
  56. /**
  57. * Replaces a config with another config to allow us to put strings
  58. * in the config array that will be replaced by objects before
  59. * normalization.
  60. * @param {Object} config The config to preprocess.
  61. * @returns {Object} The preprocessed config.
  62. */
  63. [ConfigArraySymbol.preprocessConfig](config) {
  64. if (config === "eslint:recommended") {
  65. return recommendedConfig;
  66. }
  67. if (config === "eslint:all") {
  68. /*
  69. * Load `eslint-all.js` here instead of at the top level to avoid loading all rule modules
  70. * when it isn't necessary. `eslint-all.js` reads `meta` of rule objects to filter out deprecated ones,
  71. * so requiring `eslint-all.js` module loads all rule modules as a consequence.
  72. */
  73. return require("../../conf/eslint-all");
  74. }
  75. return config;
  76. }
  77. /**
  78. * Finalizes the config by replacing plugin references with their objects
  79. * and validating rule option schemas.
  80. * @param {Object} config The config to finalize.
  81. * @returns {Object} The finalized config.
  82. * @throws {TypeError} If the config is invalid.
  83. */
  84. [ConfigArraySymbol.finalizeConfig](config) {
  85. const { plugins, languageOptions, processor } = config;
  86. // Check parser value
  87. if (languageOptions && languageOptions.parser && typeof languageOptions.parser === "string") {
  88. const { pluginName, objectName: parserName } = splitPluginIdentifier(languageOptions.parser);
  89. if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[parserName]) {
  90. throw new TypeError(`Key "parser": Could not find "${parserName}" in plugin "${pluginName}".`);
  91. }
  92. languageOptions.parser = plugins[pluginName].parsers[parserName];
  93. }
  94. // Check processor value
  95. if (processor && typeof processor === "string") {
  96. const { pluginName, objectName: processorName } = splitPluginIdentifier(processor);
  97. if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[processorName]) {
  98. throw new TypeError(`Key "processor": Could not find "${processorName}" in plugin "${pluginName}".`);
  99. }
  100. config.processor = plugins[pluginName].processors[processorName];
  101. }
  102. ruleValidator.validate(config);
  103. return config;
  104. }
  105. /* eslint-enable class-methods-use-this -- Desired as instance method */
  106. }
  107. exports.FlatConfigArray = FlatConfigArray;