UNPKG

@nx/eslint

Version:

The ESLint plugin for Nx contains executors, generators and utilities used for linting JavaScript/TypeScript projects within an Nx workspace.

154 lines (153 loc) • 7.39 kB
"use strict"; 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'); } }