@nx/eslint
Version:
154 lines (153 loc) • 7.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.migrateConfigToMonorepoStyle = migrateConfigToMonorepoStyle;
exports.findLintTarget = findLintTarget;
const devkit_1 = require("@nx/devkit");
const path_1 = require("path");
const eslint_file_1 = require("../utils/eslint-file");
const global_eslint_config_1 = require("./global-eslint-config");
const flat_config_1 = require("../../utils/flat-config");
const versions_1 = require("../../utils/versions");
const ast_utils_1 = require("../utils/flat-config/ast-utils");
const plugin_1 = require("../utils/plugin");
const config_file_1 = require("../../utils/config-file");
function migrateConfigToMonorepoStyle(projects, tree, unitTestRunner, eslintConfigFormat, keepExistingVersions) {
const rootEslintConfig = (0, eslint_file_1.findEslintFile)(tree);
let skipCleanup = false;
if (rootEslintConfig) {
// We do not want to mix the formats
const fileExtension = (0, path_1.extname)(rootEslintConfig);
if (fileExtension === '.mjs' || fileExtension === '.cjs') {
eslintConfigFormat = fileExtension.slice(1);
}
else {
eslintConfigFormat = (0, eslint_file_1.determineEslintConfigFormat)(tree.read(rootEslintConfig, 'utf-8'));
}
}
if (rootEslintConfig?.match(/\.base\./) &&
!projects.some((p) => p.root === '.')) {
// if the migration has been run already, we need to rename the base config
// and only update the extends paths
tree.rename(rootEslintConfig, rootEslintConfig.replace('.base.', '.'));
skipCleanup = true;
}
else {
if ((0, flat_config_1.useFlatConfig)(tree)) {
// we need this for the compat
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
'@eslint/js': versions_1.eslintVersion,
}, undefined, keepExistingVersions);
tree.write(tree.exists(`eslint.config.${eslintConfigFormat}`)
? `eslint.base.config.${eslintConfigFormat}`
: `eslint.config.${eslintConfigFormat}`, (0, global_eslint_config_1.getGlobalFlatEslintConfiguration)(eslintConfigFormat));
}
else {
const eslintFile = (0, eslint_file_1.findEslintFile)(tree, '.');
(0, devkit_1.writeJson)(tree, eslintFile ? '.eslintrc.base.json' : '.eslintrc.json', (0, global_eslint_config_1.getGlobalEsLintConfiguration)(unitTestRunner));
}
}
// update extends in all projects' eslint configs
projects.forEach((project) => {
let eslintFile;
const lintTarget = findLintTarget(project);
if (lintTarget) {
// If target is configured in project.json, read file from target options.
eslintFile =
lintTarget.options?.eslintConfig || (0, eslint_file_1.findEslintFile)(tree, project.root);
}
else if ((0, plugin_1.hasEslintPlugin)(tree)) {
// Otherwise, if `@nx/eslint/plugin` is used, match any of the known config files.
for (const f of config_file_1.ESLINT_CONFIG_FILENAMES) {
if (tree.exists((0, devkit_1.joinPathFragments)(project.root, f))) {
eslintFile = f;
break;
}
}
}
if (eslintFile) {
const projectEslintPath = (0, devkit_1.joinPathFragments)(project.root, eslintFile);
if (skipCleanup) {
const content = tree.read(projectEslintPath, 'utf-8');
tree.write(projectEslintPath, content.replace(rootEslintConfig, rootEslintConfig.replace('.base.', '.')));
}
else {
migrateEslintFile(projectEslintPath, tree);
}
}
});
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, {
'@nx/eslint-plugin': versions_1.nxVersion,
});
}
function findLintTarget(project) {
return Object.values(project.targets ?? {}).find((target) => target.executor === '@nx/eslint:lint' ||
target.executor === '@nx/linter:eslint');
}
function migrateEslintFile(projectEslintPath, tree) {
const baseFile = (0, eslint_file_1.findEslintFile)(tree);
if ((0, eslint_file_1.isEslintConfigSupported)(tree)) {
if ((0, flat_config_1.useFlatConfig)(tree)) {
let config = tree.read(projectEslintPath, 'utf-8');
// remove @nx plugin
config = (0, ast_utils_1.removePlugin)(config, '@nx', '@nx/eslint-plugin-nx');
// if base config is cjs, we will need to import it using async import
config = (0, ast_utils_1.addImportToFlatConfig)(config, 'baseConfig', `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}${baseFile}`);
config = (0, ast_utils_1.addBlockToFlatConfigExport)(config, (0, ast_utils_1.generateSpreadElement)('baseConfig'), { insertAtTheEnd: false });
// cleanup file extends
config = (0, ast_utils_1.removeCompatExtends)(config, [
'plugin:@nx/typescript',
'plugin:@nx/javascript',
]);
config = (0, ast_utils_1.removePredefinedConfigs)(config, '@nx/eslint-plugin', 'nx', [
'flat/base',
'flat/typescript',
'flat/javascript',
]);
tree.write(projectEslintPath, config);
}
else {
(0, devkit_1.updateJson)(tree, projectEslintPath, (json) => {
// we have a new root now
delete json.root;
// remove nrwl/nx plugins
if (json.plugins) {
json.plugins = json.plugins.filter((p) => p !== '@nx');
if (json.plugins.length === 0) {
delete json.plugins;
}
}
// add extends
json.extends = json.extends || [];
// ensure extends is an array
if (typeof json.extends === 'string') {
json.extends = [json.extends];
}
const pathToRootConfig = `${(0, devkit_1.offsetFromRoot)((0, path_1.dirname)(projectEslintPath))}${baseFile}`;
if (json.extends.indexOf(pathToRootConfig) === -1) {
json.extends.push(pathToRootConfig);
}
// cleanup overrides
if (json.overrides) {
json.overrides.forEach((override) => {
if (override.extends) {
override.extends = override.extends.filter((ext) => ext !== 'plugin:@nx/typescript' &&
ext !== 'plugin:@nx/javascript');
if (override.extends.length === 0) {
delete override.extends;
}
}
});
}
return json;
});
}
return;
}
if (projectEslintPath.endsWith('.yml') ||
projectEslintPath.endsWith('.yaml')) {
console.warn('YAML eslint config is not supported yet for migration');
}
if (projectEslintPath.endsWith('.js') || projectEslintPath.endsWith('.cjs')) {
console.warn('JS eslint config is not supported yet for migration');
}
}