|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import createDebug from "debug"; |
|
import path from "path"; |
|
|
|
import environments from "../conf/environments.js"; |
|
import { ConfigArrayFactory } from "./config-array-factory.js"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const debug = createDebug("eslintrc:flat-compat"); |
|
const cafactory = Symbol("cafactory"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function translateESLintRC(eslintrcConfig, { |
|
resolveConfigRelativeTo, |
|
resolvePluginsRelativeTo, |
|
pluginEnvironments, |
|
pluginProcessors |
|
}) { |
|
|
|
const flatConfig = {}; |
|
const configs = []; |
|
const languageOptions = {}; |
|
const linterOptions = {}; |
|
const keysToCopy = ["settings", "rules", "processor"]; |
|
const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"]; |
|
const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"]; |
|
|
|
|
|
for (const key of keysToCopy) { |
|
if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") { |
|
flatConfig[key] = eslintrcConfig[key]; |
|
} |
|
} |
|
|
|
|
|
for (const key of languageOptionsKeysToCopy) { |
|
if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") { |
|
|
|
|
|
flatConfig.languageOptions = languageOptions; |
|
|
|
if (key === "parser") { |
|
debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`); |
|
|
|
if (eslintrcConfig[key].error) { |
|
throw eslintrcConfig[key].error; |
|
} |
|
|
|
languageOptions[key] = eslintrcConfig[key].definition; |
|
continue; |
|
} |
|
|
|
|
|
if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") { |
|
languageOptions[key] = { |
|
...eslintrcConfig[key] |
|
}; |
|
} else { |
|
languageOptions[key] = eslintrcConfig[key]; |
|
} |
|
} |
|
} |
|
|
|
|
|
for (const key of linterOptionsKeysToCopy) { |
|
if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") { |
|
flatConfig.linterOptions = linterOptions; |
|
linterOptions[key] = eslintrcConfig[key]; |
|
} |
|
} |
|
|
|
|
|
if (languageOptions.parserOptions) { |
|
|
|
if ("ecmaVersion" in languageOptions.parserOptions) { |
|
languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion; |
|
delete languageOptions.parserOptions.ecmaVersion; |
|
} |
|
|
|
if ("sourceType" in languageOptions.parserOptions) { |
|
languageOptions.sourceType = languageOptions.parserOptions.sourceType; |
|
delete languageOptions.parserOptions.sourceType; |
|
} |
|
|
|
|
|
if (Object.keys(languageOptions.parserOptions).length === 0) { |
|
delete languageOptions.parserOptions; |
|
} |
|
} |
|
|
|
|
|
if (eslintrcConfig.criteria) { |
|
flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)]; |
|
} |
|
|
|
|
|
if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") { |
|
debug(`Translating plugins: ${eslintrcConfig.plugins}`); |
|
|
|
flatConfig.plugins = {}; |
|
|
|
for (const pluginName of Object.keys(eslintrcConfig.plugins)) { |
|
|
|
debug(`Translating plugin: ${pluginName}`); |
|
debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`); |
|
|
|
const { original: plugin, error } = eslintrcConfig.plugins[pluginName]; |
|
|
|
if (error) { |
|
throw error; |
|
} |
|
|
|
flatConfig.plugins[pluginName] = plugin; |
|
|
|
|
|
if (plugin.processors) { |
|
for (const processorName of Object.keys(plugin.processors)) { |
|
if (processorName.startsWith(".")) { |
|
debug(`Assigning processor: ${pluginName}/${processorName}`); |
|
|
|
configs.unshift({ |
|
files: [`**/*${processorName}`], |
|
processor: pluginProcessors.get(`${pluginName}/${processorName}`) |
|
}); |
|
} |
|
|
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") { |
|
for (const envName of Object.keys(eslintrcConfig.env)) { |
|
|
|
|
|
if (eslintrcConfig.env[envName]) { |
|
debug(`Translating environment: ${envName}`); |
|
|
|
if (environments.has(envName)) { |
|
|
|
|
|
configs.unshift(...translateESLintRC({ |
|
criteria: eslintrcConfig.criteria, |
|
...environments.get(envName) |
|
}, { |
|
resolveConfigRelativeTo, |
|
resolvePluginsRelativeTo |
|
})); |
|
} else if (pluginEnvironments.has(envName)) { |
|
|
|
|
|
configs.push(...translateESLintRC({ |
|
criteria: eslintrcConfig.criteria, |
|
...pluginEnvironments.get(envName) |
|
}, { |
|
resolveConfigRelativeTo, |
|
resolvePluginsRelativeTo |
|
})); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
if (Object.keys(flatConfig).length > 0) { |
|
configs.push(flatConfig); |
|
} |
|
|
|
return configs; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FlatCompat { |
|
|
|
constructor({ |
|
baseDirectory = process.cwd(), |
|
resolvePluginsRelativeTo = baseDirectory, |
|
recommendedConfig, |
|
allConfig |
|
} = {}) { |
|
this.baseDirectory = baseDirectory; |
|
this.resolvePluginsRelativeTo = resolvePluginsRelativeTo; |
|
this[cafactory] = new ConfigArrayFactory({ |
|
cwd: baseDirectory, |
|
resolvePluginsRelativeTo, |
|
getEslintAllConfig: () => { |
|
|
|
if (!allConfig) { |
|
throw new TypeError("Missing parameter 'allConfig' in FlatCompat constructor."); |
|
} |
|
|
|
return allConfig; |
|
}, |
|
getEslintRecommendedConfig: () => { |
|
|
|
if (!recommendedConfig) { |
|
throw new TypeError("Missing parameter 'recommendedConfig' in FlatCompat constructor."); |
|
} |
|
|
|
return recommendedConfig; |
|
} |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
config(eslintrcConfig) { |
|
const eslintrcArray = this[cafactory].create(eslintrcConfig, { |
|
basePath: this.baseDirectory |
|
}); |
|
|
|
const flatArray = []; |
|
let hasIgnorePatterns = false; |
|
|
|
eslintrcArray.forEach(configData => { |
|
if (configData.type === "config") { |
|
hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern; |
|
flatArray.push(...translateESLintRC(configData, { |
|
resolveConfigRelativeTo: path.join(this.baseDirectory, "__placeholder.js"), |
|
resolvePluginsRelativeTo: path.join(this.resolvePluginsRelativeTo, "__placeholder.js"), |
|
pluginEnvironments: eslintrcArray.pluginEnvironments, |
|
pluginProcessors: eslintrcArray.pluginProcessors |
|
})); |
|
} |
|
}); |
|
|
|
|
|
if (hasIgnorePatterns) { |
|
flatArray.unshift({ |
|
ignores: [filePath => { |
|
|
|
|
|
|
|
const finalConfig = eslintrcArray.extractConfig(filePath); |
|
|
|
|
|
return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath); |
|
}] |
|
}); |
|
} |
|
|
|
return flatArray; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
env(envConfig) { |
|
return this.config({ |
|
env: envConfig |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
extends(...configsToExtend) { |
|
return this.config({ |
|
extends: configsToExtend |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
plugins(...plugins) { |
|
return this.config({ |
|
plugins |
|
}); |
|
} |
|
} |
|
|
|
export { FlatCompat }; |
|
|