UNPKG

@oxlint/migrate

Version:

Generates a `.oxlintrc.json` from a existing eslint flat config

192 lines (191 loc) 6.07 kB
import * as rules from "./generated/rules.mjs"; import { nurseryRules } from "./generated/rules.mjs"; import { typescriptTypeAwareRules, rulesPrefixesForPlugins, typescriptRulesExtendEslintRules } from "./constants.mjs"; const allRules = Object.values(rules).flat(); const isValueInSet = (value, validSet) => validSet.includes(value) || Array.isArray(value) && validSet.includes(value[0]); const isActiveValue = (value) => isValueInSet(value, ["error", "warn", 1, 2]); const isOffValue = (value) => isValueInSet(value, ["off", 0]); const isErrorValue = (value) => isValueInSet(value, ["error", 1]); const isWarnValue = (value) => isValueInSet(value, ["warn", 2]); const normalizeSeverityValue = (value) => { if (value === void 0) { return value; } if (isWarnValue(value)) { if (Array.isArray(value)) { value[0] == "warn"; return value; } return "warn"; } else if (isErrorValue(value)) { if (Array.isArray(value)) { value[0] == "error"; return value; } return "error"; } if (isOffValue(value)) { if (Array.isArray(value)) { value[0] == "off"; return value; } return "off"; } return void 0; }; const transformRuleEntry = (eslintConfig, targetConfig, options) => { if (eslintConfig.rules === void 0) { return; } if (targetConfig.rules === void 0) { targetConfig.rules = {}; } for (const [rule, config] of Object.entries(eslintConfig.rules)) { if (allRules.includes(rule)) { if (!options?.withNursery && nurseryRules.includes(rule)) { options?.reporter !== void 0 && options.reporter(`unsupported rule, but in development: ${rule}`); continue; } if (!options?.typeAware && typescriptTypeAwareRules.includes(rule)) { options?.reporter !== void 0 && options.reporter( `type-aware rule detected, but \`--type-aware\` is not enabled: ${rule}` ); continue; } if (options?.merge) { if (!(rule in targetConfig.rules)) { targetConfig.rules[rule] = normalizeSeverityValue(config); } } else { targetConfig.rules[rule] = normalizeSeverityValue(config); } } else { if (isActiveValue(config)) { options?.reporter !== void 0 && options.reporter(`unsupported rule: ${rule}`); } } } }; const detectNeededRulesPlugins = (targetConfig, options) => { if (targetConfig.rules === void 0) { return; } if (targetConfig.plugins === void 0) { targetConfig.plugins = []; } for (const rule of Object.keys(targetConfig.rules)) { if (!rule.includes("/")) { continue; } let found = false; for (const [prefix, plugin] of Object.entries(rulesPrefixesForPlugins)) { if (rule.startsWith(`${prefix}/`)) { if (!targetConfig.plugins.includes(plugin)) { targetConfig.plugins.push(plugin); } found = true; } } if (!found) { options?.reporter !== void 0 && options.reporter(`unsupported plugin for rule: ${rule}`); } } if ("files" in targetConfig && targetConfig.plugins.length === 0) { delete targetConfig.plugins; } }; const cleanUpUselessOverridesPlugins = (config) => { if (config.overrides === void 0) { return; } if (config.plugins !== void 0) { for (const override of config.overrides) { if (override.plugins === void 0) { continue; } override.plugins = override.plugins.filter( (overridePlugin) => !config.plugins.includes(overridePlugin) ); if (override.plugins.length === 0) { delete override.plugins; } } } }; const cleanUpUselessOverridesRules = (config) => { if (config.rules === void 0 || config.overrides === void 0) { return; } for (const override of config.overrides) { if (override.rules === void 0) { continue; } for (const [rule, settings] of Object.entries(override.rules)) { if (config.rules[rule] === settings) { delete override.rules[rule]; } } if (Object.keys(override.rules).length === 0) { delete override.rules; } } }; const cleanUpRulesWhichAreCoveredByCategory = (config) => { if (config.rules === void 0 || config.categories === void 0) { return; } const enabledCategories = Object.entries(config.categories).filter(([, severity]) => severity === "warn" || severity === "error").map(([category]) => category); for (const [rule, settings] of Object.entries(config.rules)) { for (const category of enabledCategories) { if (`${category}Rules` in rules && // @ts-expect-error -- ts can not resolve the type rules[`${category}Rules`].includes(rule)) { if (settings === config.categories[category] || Array.isArray(settings) && settings.length === 1 && settings[0] === config.categories[category]) { delete config.rules[rule]; } } } } }; const replaceTypescriptAliasRules = (config) => { if (config.rules === void 0) { return; } for (const rule of Object.keys(config.rules)) { const prefix = "@typescript-eslint/"; if (!rule.startsWith(prefix)) { continue; } const eslintRule = rule.slice(prefix.length); if (!typescriptRulesExtendEslintRules.includes(eslintRule)) { continue; } config.rules[eslintRule] = config.rules[rule]; delete config.rules[rule]; } if (Object.keys(config.rules).length === 0) { delete config.rules; } }; const replaceNodePluginName = (config) => { if (config.rules === void 0) { return; } for (const rule of Object.keys(config.rules)) { const prefix = "n/"; if (!rule.startsWith(prefix)) { continue; } const nodeRule = `node/${rule.slice(prefix.length)}`; config.rules[nodeRule] = config.rules[rule]; delete config.rules[rule]; } }; export { cleanUpRulesWhichAreCoveredByCategory, cleanUpUselessOverridesPlugins, cleanUpUselessOverridesRules, detectNeededRulesPlugins, replaceNodePluginName, replaceTypescriptAliasRules, transformRuleEntry };