@code-pushup/eslint-plugin
Version:
Code PushUp plugin for detecting problems in source code using ESLint.📋
81 lines • 3.06 kB
JavaScript
import { builtinRules } from 'eslint/use-at-your-own-risk';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import { exists, findNearestFile, toArray, ui } from '@code-pushup/utils';
import { jsonHash } from '../hash.js';
import { isRuleOff, optionsFromRuleEntry, parseRuleId, } from '../parse.js';
export async function loadRulesForFlatConfig({ eslintrc, }) {
const config = eslintrc
? await loadConfigByPath(eslintrc)
: await loadConfigByDefaultLocation();
const configs = toArray(config);
const rules = findEnabledRulesWithOptions(configs);
return rules
.map(rule => {
const meta = findRuleMeta(rule.id, configs);
if (!meta) {
ui().logger.warning(`Cannot find metadata for rule ${rule.id}`);
return null;
}
return { ...rule, meta };
})
.filter(exists);
}
async function loadConfigByDefaultLocation() {
const flatConfigFileNames = [
'eslint.config.js',
'eslint.config.mjs',
'eslint.config.cjs',
];
const configPath = await findNearestFile(flatConfigFileNames);
if (configPath) {
return loadConfigByPath(configPath);
}
throw new Error([
`ESLint config file not found - expected ${flatConfigFileNames.join('/')} in ${process.cwd()} or some parent directory`,
'If your ESLint config is in a non-standard location, use the `eslintrc` parameter to specify the path.',
].join('\n'));
}
async function loadConfigByPath(configPath) {
const absolutePath = path.isAbsolute(configPath)
? configPath
: path.join(process.cwd(), configPath);
const url = pathToFileURL(absolutePath).toString();
const mod = (await import(url));
return 'default' in mod ? mod.default : mod;
}
function findEnabledRulesWithOptions(configs) {
const enabledRules = configs
.flatMap(({ rules }) => Object.entries(rules ?? {}))
.filter(([, entry]) => entry != null && !isRuleOff(entry))
.map(([id, entry]) => ({
id,
options: entry ? optionsFromRuleEntry(entry) : [],
}));
const uniqueRulesMap = new Map(enabledRules.map(({ id, options }) => [
`${id}::${jsonHash(options)}`,
{ id, options },
]));
return [...uniqueRulesMap.values()];
}
function findRuleMeta(ruleId, configs) {
const { plugin, name } = parseRuleId(ruleId);
if (!plugin) {
return findBuiltinRuleMeta(name);
}
return findPluginRuleMeta(plugin, name, configs);
}
function findBuiltinRuleMeta(name) {
const rule = builtinRules.get(name);
return rule?.meta;
}
function findPluginRuleMeta(plugin, name, configs) {
const config = configs.find(({ plugins = {} }) => plugin in plugins);
const rule = config?.plugins?.[plugin]?.rules?.[name];
if (typeof rule === 'function') {
ui().logger.warning(`Cannot parse metadata for rule ${plugin}/${name}, plugin registers it as a function`);
return undefined;
}
return rule?.meta;
}
//# sourceMappingURL=flat.js.map