knip 5.61.0 → 5.61.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -276,7 +276,8 @@ export class WorkspaceWorker {
276
276
  if (plugin.resolveConfig && !seen.get(key)?.has(configFilePath)) {
277
277
  if (typeof plugin.setup === 'function')
278
278
  await plugin.setup(resolveOpts);
279
- const localConfig = await loadConfigForPlugin(configFilePath, plugin, resolveOpts, pluginName);
279
+ const isLoad = typeof plugin.isLoadConfig === 'function' ? plugin.isLoadConfig(resolveOpts, this.dependencies) : true;
280
+ const localConfig = isLoad && (await loadConfigForPlugin(configFilePath, plugin, resolveOpts, pluginName));
280
281
  if (localConfig) {
281
282
  const inputs = await plugin.resolveConfig(localConfig, resolveOpts);
282
283
  for (const input of inputs)
@@ -48,7 +48,7 @@ export const getDependenciesFromScript = (script, options) => {
48
48
  .map(arg => parseNodeArgs(arg.split(' ')))
49
49
  .filter(args => args.require)
50
50
  .flatMap(arg => arg.require)
51
- .map(toDeferResolve) ?? [];
51
+ .map(id => toDeferResolve(id)) ?? [];
52
52
  if (binary in PackageManagerResolvers) {
53
53
  const resolver = PackageManagerResolvers[binary];
54
54
  return resolver(binary, args, { ...options, fromArgs });
@@ -61,8 +61,8 @@ export const resolve = (binary, _args, options) => {
61
61
  return [
62
62
  toBinary(binary, inputOpts),
63
63
  ...positionals,
64
- ...resolved.map(toDeferResolve),
65
- ...resolvedImports.map(toDeferResolve),
64
+ ...resolved.map(id => toDeferResolve(id)),
65
+ ...resolvedImports.map(id => toDeferResolve(id)),
66
66
  ...resolvedFromArgs,
67
67
  ...configFilePaths,
68
68
  ];
@@ -8,7 +8,7 @@ const entry = [];
8
8
  const production = [];
9
9
  const resolveConfig = async (config) => {
10
10
  const inputs = config?.plugins ?? [];
11
- return [...inputs].map(toDeferResolve);
11
+ return [...inputs].map(id => toDeferResolve(id));
12
12
  };
13
13
  export default {
14
14
  title,
@@ -5,14 +5,19 @@ import { api, resolveName } from './helpers.js';
5
5
  const title = 'Babel';
6
6
  const enablers = [/^@babel\//];
7
7
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
8
- const config = ['babel.config.{json,js,cjs,mjs,cts}', '.babelrc.{json,js,cjs,mjs,cts}', '.babelrc', 'package.json'];
8
+ const config = ['babel.config.{json,js,cjs,mjs,cts,ts}', '.babelrc.{json,js,cjs,mjs,cts}', '.babelrc', 'package.json'];
9
9
  const getName = (value) => [Array.isArray(value) ? value[0] : value].filter(name => typeof name === 'string');
10
10
  export const getDependenciesFromConfig = (config) => {
11
11
  const presets = config.presets?.flatMap(getName).map(name => resolveName(name, 'preset')) ?? [];
12
12
  const plugins = config.plugins?.flatMap(getName).map(name => resolveName(name, 'plugin')) ?? [];
13
13
  const nested = config.env ? Object.values(config.env).flatMap(getDependenciesFromConfig) : [];
14
14
  const overrides = config.overrides ? [config.overrides].flat().flatMap(getDependenciesFromConfig) : [];
15
- return compact([...presets.map(toDeferResolve), ...plugins.map(toDeferResolve), ...nested, ...overrides]);
15
+ return compact([
16
+ ...presets.map(id => toDeferResolve(id)),
17
+ ...plugins.map(id => toDeferResolve(id)),
18
+ ...nested,
19
+ ...overrides,
20
+ ]);
16
21
  };
17
22
  const resolveConfig = async (config) => {
18
23
  if (typeof config === 'function')
@@ -1,16 +1,11 @@
1
1
  import { toConfig } from '../../util/input.js';
2
2
  import { hasDependency } from '../../util/plugin.js';
3
3
  const title = 'Biome';
4
- const enablers = ['@biomejs/biome', 'biome'];
4
+ const enablers = ['@biomejs/biome'];
5
5
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
6
  const config = ['biome.json', 'biome.jsonc'];
7
7
  const resolveExtends = (extendsArray, options) => {
8
- return extendsArray.map(specifier => {
9
- if (specifier.endsWith('.json') || specifier.endsWith('.jsonc')) {
10
- return toConfig('biome', specifier);
11
- }
12
- return toConfig('biome', specifier, { containingFilePath: options.configFilePath });
13
- });
8
+ return extendsArray.map(specifier => toConfig('biome', specifier, { containingFilePath: options.configFilePath }));
14
9
  };
15
10
  const resolveConfig = (config, options) => {
16
11
  return [...resolveExtends(config.extends || [], options)];
@@ -10,7 +10,7 @@ const config = [
10
10
  'c{s,S}pell.json',
11
11
  ];
12
12
  const resolveConfig = config => {
13
- return [config?.import ?? []].flat().map(toDeferResolve);
13
+ return [config?.import ?? []].flat().map(id => toDeferResolve(id));
14
14
  };
15
15
  export default {
16
16
  title,
@@ -9,7 +9,7 @@ const resolveConfig = config => {
9
9
  const imports = (config?.import ? config.import : entry).map(id => toEntry(id));
10
10
  const formatters = config?.format ? config.format : [];
11
11
  const requires = config?.require ? config.require : [];
12
- return imports.concat([...formatters, ...requires].map(toDeferResolve));
12
+ return imports.concat([...formatters, ...requires].map(id => toDeferResolve(id)));
13
13
  };
14
14
  export default {
15
15
  title,
@@ -18,7 +18,7 @@ const resolveConfig = async (localConfig, options) => {
18
18
  const supportFiles = [localConfig.e2e?.supportFile || [], localConfig.component?.supportFile || []].flat();
19
19
  const inputs = await resolveDependencies(localConfig, options);
20
20
  return [
21
- ...inputs.map(toDeferResolve),
21
+ ...inputs.map(id => toDeferResolve(id)),
22
22
  ...(specPatterns.length > 0 ? specPatterns : TEST_FILE_PATTERNS).map(id => toEntry(id)),
23
23
  ...(supportFiles.length > 0 ? supportFiles : SUPPORT_FILE_PATTERNS).map(id => toEntry(id)),
24
24
  ];
@@ -9,7 +9,7 @@ export const getInputs = (config, options) => {
9
9
  return getInputsDeprecated(config, options);
10
10
  }
11
11
  const dependencies = config.flatMap(config => config.settings ? getDependenciesFromSettings(config.settings).filter(id => id !== '@typescript-eslint/parser') : []);
12
- return compact(dependencies).map(id => toDeferResolve(id));
12
+ return compact(dependencies).map(id => toDeferResolve(id, { optional: true }));
13
13
  };
14
14
  const getInputsDeprecated = (config, options) => {
15
15
  const extendsSpecifiers = config.extends ? compact([config.extends].flat().map(resolveExtendSpecifier)) : [];
@@ -24,7 +24,7 @@ const getInputsDeprecated = (config, options) => {
24
24
  const settings = config.settings ? getDependenciesFromSettings(config.settings) : [];
25
25
  const rules = getDependenciesFromRules({});
26
26
  const overrides = config.overrides ? [config.overrides].flat().flatMap(d => getInputsDeprecated(d, options)) : [];
27
- const deferred = compact([...extendsSpecifiers, ...plugins, parser, ...settings, ...rules]).map(toDeferResolve);
27
+ const deferred = compact([...extendsSpecifiers, ...plugins, parser, ...settings, ...rules]).map(id => toDeferResolve(id));
28
28
  return [...extendConfigs, ...deferred, ...babelDependencies, ...overrides];
29
29
  };
30
30
  const isQualifiedSpecifier = (specifier) => specifier === 'eslint' ||
@@ -1,4 +1,4 @@
1
- import type { IsPluginEnabled, ResolveConfig } from '../../types/config.js';
1
+ import type { IsLoadConfig, IsPluginEnabled, ResolveConfig } from '../../types/config.js';
2
2
  import type { ESLintConfigDeprecated } from './types.js';
3
3
  export declare const docs: {
4
4
  note: string;
@@ -8,8 +8,8 @@ declare const _default: {
8
8
  enablers: string[];
9
9
  isEnabled: IsPluginEnabled;
10
10
  packageJsonPath: string;
11
- entry: string[];
12
11
  config: string[];
12
+ isLoadConfig: IsLoadConfig;
13
13
  resolveConfig: ResolveConfig<ESLintConfigDeprecated>;
14
14
  };
15
15
  export default _default;
@@ -5,24 +5,29 @@ const enablers = ['eslint', '@eslint/js'];
5
5
  const isEnabled = ({ dependencies, manifest }) => hasDependency(dependencies, enablers) ||
6
6
  Boolean(manifest.name && /(^eslint-config|\/eslint-config)/.test(manifest.name));
7
7
  const packageJsonPath = 'eslintConfig';
8
- const entry = ['eslint.config.{js,cjs,mjs,ts,cts,mts}'];
9
- const config = ['.eslintrc', '.eslintrc.{js,json,cjs}', '.eslintrc.{yml,yaml}', 'package.json'];
8
+ const config = [
9
+ 'eslint.config.{js,cjs,mjs,ts,cts,mts}',
10
+ '.eslintrc',
11
+ '.eslintrc.{js,json,cjs}',
12
+ '.eslintrc.{yml,yaml}',
13
+ 'package.json',
14
+ ];
15
+ const isLoadConfig = ({ manifest }, dependencies) => {
16
+ const version = manifest.devDependencies?.['eslint'] || manifest.dependencies?.['eslint'];
17
+ if (version) {
18
+ const major = version.match(/\d+/);
19
+ if (major && Number.parseInt(major[0], 10) === 9 && dependencies.has('eslint-config-next')) {
20
+ return false;
21
+ }
22
+ }
23
+ return true;
24
+ };
10
25
  const resolveConfig = (localConfig, options) => getInputs(localConfig, options);
11
26
  const note = `### ESLint v9
12
27
 
13
- Only regular \`import\` statements are considered by default.
14
- The configuration object is not resolved to find dependencies for \`settings\` such as \`"eslint-import-resolver-typescript"\`.
15
- To enable this, lift the \`entry\` to a \`config\` file like so:
16
-
17
- \`\`\`json
18
- {
19
- "eslint": ["eslint.config.ts"]
20
- }
21
- \`\`\`
22
-
23
- This is not enabled by default, since this exception may be thrown by a \`@rushstack/eslint-*\` package:
28
+ The ESLint plugin config resolver is disabled when using \`eslint-config-next\` (\`next lint\`).
24
29
 
25
- > \`Error: Failed to patch ESLint because the calling module was not recognized.\`
30
+ Root cause: [microsoft/rushstack#4965](https://github.com/microsoft/rushstack/issues/4965)/[#5049](https://github.com/microsoft/rushstack/issues/5049)
26
31
 
27
32
  ### ESLint v8
28
33
 
@@ -41,7 +46,7 @@ export default {
41
46
  enablers,
42
47
  isEnabled,
43
48
  packageJsonPath,
44
- entry,
45
49
  config,
50
+ isLoadConfig,
46
51
  resolveConfig,
47
52
  };
@@ -17,7 +17,7 @@ const resolveConfig = async (localConfig, options) => {
17
17
  if (/gatsby-config/.test(configFileName)) {
18
18
  return localConfig.plugins
19
19
  .map(plugin => (typeof plugin === 'string' ? plugin : plugin.resolve))
20
- .map(toDeferResolve);
20
+ .map(id => toDeferResolve(id));
21
21
  }
22
22
  if (/gatsby-node/.test(configFileName)) {
23
23
  const plugins = new Set();
@@ -179,8 +179,8 @@ export declare const Plugins: {
179
179
  enablers: string[];
180
180
  isEnabled: import("../types/config.js").IsPluginEnabled;
181
181
  packageJsonPath: string;
182
- entry: string[];
183
182
  config: string[];
183
+ isLoadConfig: import("../types/config.js").IsLoadConfig;
184
184
  resolveConfig: import("../types/config.js").ResolveConfig<import("./eslint/types.js").ESLintConfigDeprecated>;
185
185
  };
186
186
  expo: {
@@ -9,7 +9,7 @@ const config = ['package.json', ...toCosmiconfig('linthtml')];
9
9
  const resolveConfig = config => {
10
10
  const extensions = config.extends ?? [];
11
11
  const plugins = config.plugins ?? [];
12
- return [extensions, plugins].flat().map(toDeferResolve);
12
+ return [extensions, plugins].flat().map(id => toDeferResolve(id));
13
13
  };
14
14
  export default {
15
15
  title,
@@ -35,7 +35,7 @@ const resolveConfig = async (config) => {
35
35
  inputs.push(transformer.minifierPath);
36
36
  if (transformer?.babelTransformerPath)
37
37
  inputs.push(transformer.babelTransformerPath);
38
- return Array.from(i).concat([...inputs].map(toDeferResolve));
38
+ return Array.from(i).concat([...inputs].map(id => toDeferResolve(id)));
39
39
  };
40
40
  const note = `False positives for platform-specific unused files?
41
41
  Override the default \`entry\` patterns to match platforms and extensions.`;
@@ -21,7 +21,19 @@ const args = {
21
21
  positional: true,
22
22
  nodeImportArgs: true,
23
23
  resolve: ['test-reporter'],
24
- boolean: ['deprecation', 'experimental-strip-types', 'harmony', 'test-only', 'test', 'warnings', 'watch'],
24
+ boolean: [
25
+ 'deprecation',
26
+ 'experimental-strip-types',
27
+ 'experimental-transform-types',
28
+ 'harmony',
29
+ 'inspect-brk',
30
+ 'inspect-wait',
31
+ 'inspect',
32
+ 'test-only',
33
+ 'test',
34
+ 'warnings',
35
+ 'watch',
36
+ ],
25
37
  args: (args) => args.filter(arg => !/--test-reporter[= ](spec|tap|dot|junit|lcov)/.test(arg)),
26
38
  };
27
39
  export default {
@@ -7,7 +7,7 @@ const config = ['.nycrc', '.nycrc.{json,yml,yaml}', 'nyc.config.js', 'package.js
7
7
  const resolveConfig = config => {
8
8
  const extend = config?.extends ?? [];
9
9
  const requires = config?.require ?? [];
10
- return [extend, requires].flat().map(toDeferResolve);
10
+ return [extend, requires].flat().map(id => toDeferResolve(id));
11
11
  };
12
12
  export default {
13
13
  title,
@@ -24,7 +24,7 @@ export const resolveConfig = async (localConfig, options) => {
24
24
  });
25
25
  return projects
26
26
  .flatMap(config => toEntryPatterns(config.testMatch ?? entry, cwd, configFileDir, config, localConfig))
27
- .concat(reporters.map(toDeferResolve));
27
+ .concat(reporters.map(id => toDeferResolve(id)));
28
28
  };
29
29
  const args = {
30
30
  binaries: ['playwright'],
@@ -19,7 +19,7 @@ const resolveConfig = config => {
19
19
  return [];
20
20
  })
21
21
  : [];
22
- const inputs = plugins.map(toDeferResolve);
22
+ const inputs = plugins.map(id => toDeferResolve(id));
23
23
  return ['tailwindcss', '@tailwindcss/postcss'].some(tailwindPlugin => plugins.includes(tailwindPlugin))
24
24
  ? [...inputs, toDependency('postcss')]
25
25
  : inputs;
@@ -18,7 +18,7 @@ const resolveConfig = async (localConfig) => {
18
18
  ];
19
19
  return [...entries, ...decoratorEntry]
20
20
  .map(id => toEntry(id))
21
- .concat((localConfig?.plugins ?? []).map(toDeferResolve));
21
+ .concat((localConfig?.plugins ?? []).map(id => toDeferResolve(id)));
22
22
  };
23
23
  export default {
24
24
  title,
@@ -15,7 +15,7 @@ const resolveConfig = config => {
15
15
  return [];
16
16
  })
17
17
  .map(plugin => (plugin.startsWith('remark-') ? plugin : `remark-${plugin}`)) ?? [];
18
- return plugins.map(toDeferResolve);
18
+ return plugins.map(id => toDeferResolve(id));
19
19
  };
20
20
  export default {
21
21
  title,
@@ -15,7 +15,7 @@ const excludePackages = [
15
15
  ];
16
16
  const resolveConfig = config => {
17
17
  const plugins = (config?.plugins ?? []).map(plugin => (Array.isArray(plugin) ? plugin[0] : plugin));
18
- return plugins.filter(plugin => !excludePackages.includes(plugin)).map(toDeferResolve);
18
+ return plugins.filter(plugin => !excludePackages.includes(plugin)).map(id => toDeferResolve(id));
19
19
  };
20
20
  export default {
21
21
  title,
@@ -33,7 +33,7 @@ const resolveConfig = async (localConfig, options) => {
33
33
  const frameworks = framework ? [framework] : [];
34
34
  return [
35
35
  ...patterns.map(id => toEntry(id)),
36
- ...addons.map(toDeferResolve),
36
+ ...addons.map(id => toDeferResolve(id)),
37
37
  ...builderPackages.map(id => toDependency(id)),
38
38
  ...frameworks.map(id => toDependency(id)),
39
39
  ];
@@ -10,7 +10,7 @@ const resolveConfig = localConfig => {
10
10
  ? localConfig.checkers.map(checker => `@stryker-mutator/${checker}-checker`)
11
11
  : [];
12
12
  const plugins = localConfig.plugins ?? [];
13
- return [...runners, ...checkers, ...plugins].map(toDeferResolve);
13
+ return [...runners, ...checkers, ...plugins].map(id => toDeferResolve(id));
14
14
  };
15
15
  export default {
16
16
  title,
@@ -16,7 +16,7 @@ const resolveConfig = config => {
16
16
  const cfg = 'typedocOptions' in config ? config.typedocOptions : config;
17
17
  const plugins = cfg?.plugin ?? [];
18
18
  const themes = cfg?.theme ?? [];
19
- return [...plugins, ...themes].map(toDeferResolve);
19
+ return [...plugins, ...themes].map(id => toDeferResolve(id));
20
20
  };
21
21
  const args = {
22
22
  resolve: ['plugin', 'theme'],
@@ -24,7 +24,12 @@ const resolveConfig = async (localConfig, options) => {
24
24
  ? compilerOptions.plugins.map(plugin => (typeof plugin === 'object' && 'name' in plugin ? plugin.name : ''))
25
25
  : [];
26
26
  const importHelpers = compilerOptions?.importHelpers ? ['tslib'] : [];
27
- return compact([...extend, ...references, ...[...types, ...plugins, ...importHelpers].map(toDeferResolve), ...jsx]);
27
+ return compact([
28
+ ...extend,
29
+ ...references,
30
+ ...[...types, ...plugins, ...importHelpers].map(id => toDeferResolve(id)),
31
+ ...jsx,
32
+ ]);
28
33
  };
29
34
  const args = {
30
35
  binaries: ['tsc'],
@@ -8,7 +8,7 @@ const unused = (options) => `Remove from ${type(options.type)}${options.workspac
8
8
  const empty = (options) => `Refine ${type(options.type)}${workspace(options)}: ${id(options.identifier)} (no files found)`;
9
9
  const remove = (options) => `Remove ${type(options.type)}${workspace(options)}: ${id(options.identifier)}`;
10
10
  const add = (options) => `Add to or refine in ${yellow('workspaces')}: ${id(options.identifier)} (${options.size} unused files)`;
11
- const topLevel = (options) => `Remove or move unused top-level ${type(options.type)} to ${yellow('"."')} workspace: ${id(options.identifier)}`;
11
+ const topLevel = (options) => `Remove or move unused top-level ${type(options.type)} to one of ${yellow('workspaces')}: ${id(options.identifier)}`;
12
12
  const hintPrinters = new Map([
13
13
  ['ignoreBinaries', { print: unused }],
14
14
  ['ignoreDependencies', { print: unused }],
@@ -92,6 +92,7 @@ export interface PluginOptions extends BaseOptions {
92
92
  }
93
93
  type PluginSetup = (options: PluginOptions) => Promise<void> | void;
94
94
  type PluginTeardown = (options: PluginOptions) => Promise<void> | void;
95
+ export type IsLoadConfig = (options: PluginOptions, dependencies: Set<string>) => boolean;
95
96
  export type ResolveConfig<T = any> = (config: T, options: PluginOptions) => Promise<Input[]> | Input[];
96
97
  export type Resolve = (options: PluginOptions) => Promise<Input[]> | Input[];
97
98
  export type GetSourceFile = (filePath: string) => ts.SourceFile | undefined;
@@ -113,6 +114,7 @@ export interface Plugin {
113
114
  project?: string[];
114
115
  setup?: PluginSetup;
115
116
  teardown?: PluginTeardown;
117
+ isLoadConfig?: IsLoadConfig;
116
118
  resolveConfig?: ResolveConfig;
117
119
  resolve?: Resolve;
118
120
  resolveFromAST?: ResolveFromAST;
@@ -44,7 +44,7 @@ export declare const isConfig: (input: Input) => input is ConfigInput;
44
44
  export declare const toDependency: (specifier: string, options?: Options) => Input;
45
45
  export declare const isDependency: (input: Input) => boolean;
46
46
  export declare const toProductionDependency: (specifier: string) => Input;
47
- export declare const toDeferResolve: (specifier: string) => Input;
47
+ export declare const toDeferResolve: (specifier: string, options?: Options) => Input;
48
48
  export declare const isDeferResolve: (input: Input) => boolean;
49
49
  export declare const toDeferResolveProductionEntry: (specifier: string, options?: Options) => Input;
50
50
  export declare const isDeferResolveProductionEntry: (input: Input) => boolean;
@@ -35,7 +35,11 @@ export const toProductionDependency = (specifier) => ({
35
35
  specifier,
36
36
  production: true,
37
37
  });
38
- export const toDeferResolve = (specifier) => ({ type: 'deferResolve', specifier });
38
+ export const toDeferResolve = (specifier, options = {}) => ({
39
+ type: 'deferResolve',
40
+ specifier,
41
+ ...options,
42
+ });
39
43
  export const isDeferResolve = (input) => input.type === 'deferResolve';
40
44
  export const toDeferResolveProductionEntry = (specifier, options = {}) => ({
41
45
  type: 'deferResolveEntry',
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "5.61.0";
1
+ export declare const version = "5.61.2";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '5.61.0';
1
+ export const version = '5.61.2';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "5.61.0",
3
+ "version": "5.61.2",
4
4
  "description": "Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://knip.dev",
6
6
  "repository": {