UNPKG

knip

Version:

Find unused files, dependencies and exports in your TypeScript and JavaScript projects

71 lines (70 loc) 3.84 kB
import { compact } from '../../util/array.js'; import { toConfig, toDeferResolve } from '../../util/input.js'; import { getPackageNameFromFilePath, getPackageNameFromModuleSpecifier } from '../../util/modules.js'; import { isAbsolute, isInternal } from '../../util/path.js'; import { getDependenciesFromConfig } from '../babel/index.js'; export const getDependencies = (config, options) => { const extendsSpecifiers = config.extends ? compact([config.extends].flat().map(resolveExtendSpecifier)) : []; if (extendsSpecifiers.some(specifier => specifier?.startsWith('eslint-plugin-prettier'))) extendsSpecifiers.push('eslint-config-prettier'); const extendConfigs = extendsSpecifiers.map(specifier => toConfig('eslint', specifier, options.configFilePath)); const plugins = config.plugins ? config.plugins.map(resolvePluginSpecifier) : []; const parser = config.parser ?? config.parserOptions?.parser; const babelDependencies = config.parserOptions?.babelOptions ? getDependenciesFromConfig(config.parserOptions.babelOptions) : []; const settings = config.settings ? getDependenciesFromSettings(config.settings) : []; const rules = getDependenciesFromRules({}); const overrides = config.overrides ? [config.overrides].flat().flatMap(d => getDependencies(d, options)) : []; const x = compact([...extendsSpecifiers, ...plugins, parser, ...settings, ...rules]).map(toDeferResolve); return [...extendConfigs, ...x, ...babelDependencies, ...overrides]; }; const isQualifiedSpecifier = (specifier) => specifier === 'eslint' || /\/eslint-(config|plugin)$/.test(specifier) || /.+eslint-(config|plugin)\//.test(specifier) || /eslint-(config|plugin)-/.test(specifier); const resolveSpecifier = (namespace, rawSpecifier) => { const specifier = rawSpecifier.replace(/(^plugin:|:.+$)/, ''); if (isQualifiedSpecifier(specifier)) return specifier; if (!specifier.startsWith('@')) { const id = rawSpecifier.startsWith('plugin:') ? getPackageNameFromModuleSpecifier(specifier) : specifier.split('/')[0]; return `${namespace}-${id}`; } const [scope, name, ...rest] = specifier.split('/'); if (rawSpecifier.startsWith('plugin:') && rest.length === 0) return [scope, namespace].join('/'); return [scope, name ? `${namespace}-${name}` : namespace, ...rest].join('/'); }; const resolvePluginSpecifier = (specifier) => resolveSpecifier('eslint-plugin', specifier); const resolveExtendSpecifier = (specifier) => { if (isInternal(specifier)) return; const namespace = specifier.startsWith('plugin:') ? 'eslint-plugin' : 'eslint-config'; return resolveSpecifier(namespace, specifier); }; const getDependenciesFromRules = (rules = {}) => Object.keys(rules).flatMap(ruleKey => ruleKey.includes('/') ? [resolveSpecifier('eslint-plugin', ruleKey.split('/').slice(0, -1).join('/'))] : []); const getDependenciesFromSettings = (settings = {}) => { return Object.entries(settings).flatMap(([settingKey, settings]) => { if (settingKey === 'import/resolver') { return (typeof settings === 'string' ? [settings] : Object.keys(settings)) .filter(key => key !== 'node') .map(key => { if (isInternal(key)) return key; if (isAbsolute(key)) return getPackageNameFromFilePath(key); return `eslint-import-resolver-${key}`; }); } if (settingKey === 'import/parsers') { return (typeof settings === 'string' ? [settings] : Object.keys(settings)).map(key => { if (isAbsolute(key)) return getPackageNameFromFilePath(key); return key; }); } }); };