UNPKG

@nx/eslint

Version:

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

108 lines (107 loc) 5.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = update; const devkit_1 = require("@nx/devkit"); const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils"); const eslint_file_1 = require("../../generators/utils/eslint-file"); const project_configuration_utils_1 = require("nx/src/project-graph/utils/project-configuration-utils"); async function update(tree) { const nxJson = (0, devkit_1.readNxJson)(tree); // Don't override anything if there are already target defaults for eslint if (nxJson.targetDefaults?.['@nx/eslint:lint']) { return; } nxJson.targetDefaults ??= {}; const graph = await (0, devkit_1.createProjectGraphAsync)(); const lintTargets = new Set(); (0, executor_options_utils_1.forEachExecutorOptionsInGraph)(graph, '@nx/eslint:lint', (value, proj, targetName) => { lintTargets.add(targetName); }); // Workspace does not use eslint? if (lintTargets.size === 0) { return; } const lintDefaults = (nxJson.targetDefaults['@nx/eslint:lint'] = {}); // All eslint targets have the same name if (lintTargets.size === 1) { const targetName = Array.from(lintTargets)[0]; if (nxJson.targetDefaults[targetName]) { Object.assign(lintDefaults, nxJson.targetDefaults[targetName]); } } lintDefaults.cache ??= true; if (!lintDefaults.inputs) { const eslintConfig = (0, eslint_file_1.findEslintFile)(tree); lintDefaults.inputs = [ 'default', ...(eslintConfig ? [`{workspaceRoot}/${eslintConfig}`] : []), '{workspaceRoot}/tools/eslint-rules/**/*', ]; } // Cleanup old target defaults const projects = graph.nodes; const projectMap = (0, devkit_1.getProjects)(tree); for (const [targetDefaultKey, targetDefault] of Object.entries(nxJson.targetDefaults)) { if (!isTargetDefaultUsed(targetDefault, nxJson.targetDefaults, projects, projectMap)) { delete nxJson.targetDefaults[targetDefaultKey]; } } let addOutputs = false; (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/eslint:lint', (options, proj, targetName, configuration) => { const projConfig = projectMap.get(proj); // modify lint file patterns if (options.lintFilePatterns) { const projectRootRegex = new RegExp(`^${projConfig.root}/`); projConfig.targets[targetName].options.lintFilePatterns = options.lintFilePatterns .filter((filePattern) => filePattern !== '{projectRoot}' && filePattern !== projConfig.root) .map((filePattern) => filePattern.replace(projectRootRegex, '{projectRoot}/')); // remove lintFilePatterns if empty if (projConfig.targets[targetName].options.lintFilePatterns.length === 0) { delete projConfig.targets[targetName].options.lintFilePatterns; } } // remove inputs if they are not bringing any new inputs if (projConfig.targets[targetName].inputs && projConfig.targets[targetName].inputs.every((i) => lintDefaults.inputs.includes(i))) { delete projConfig.targets[targetName].inputs; } // remove obsolete eslint config definition, unless it's a custom one const projectEslintConfig = (0, eslint_file_1.findEslintFile)(tree, projConfig.root); if (options.eslintConfig === `${projConfig.root}/${projectEslintConfig}` || options.eslintConfig === `{projectRoot}/${projectEslintConfig}`) { delete projConfig.targets[targetName].options.eslintConfig; } // remove options if empty if (Object.keys(projConfig.targets[targetName]?.options ?? {}).length === 0) { delete projConfig.targets[targetName].options; } // track output if (options.outputFile) { addOutputs = true; } if (projConfig.targets[targetName].outputs?.length === 1 && projConfig.targets[targetName].outputs[0] === '{options.outputFile}') { delete projConfig.targets[targetName].outputs; } (0, devkit_1.updateProjectConfiguration)(tree, proj, projConfig); }); if (addOutputs) { lintDefaults.outputs = ['{options.outputFile}']; } (0, devkit_1.updateNxJson)(tree, nxJson); await (0, devkit_1.formatFiles)(tree); } function isTargetDefaultUsed(targetDefault, targetDefaults, projects, projectMap) { for (const p of Object.values(projects)) { for (const targetName in p.data?.targets ?? {}) { if ((0, project_configuration_utils_1.readTargetDefaultsForTarget)(targetName, targetDefaults, // It might seem like we should use the graph here too but we don't want to pass an executor which was processed in the graph projectMap.get(p.name)?.targets?.[targetName]?.executor) === targetDefault) { return true; } } } return false; }