knip 2.6.1 → 2.7.1

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.
package/README.md CHANGED
@@ -133,12 +133,12 @@ Using workspaces in a monorepo? Please see [workspaces][1] for more details abou
133
133
  --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)
134
134
  --dependencies Shortcut for --include dependencies,unlisted,unresolved
135
135
  --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
136
- --no-progress Don't show dynamic progress updates
136
+ -n, --no-progress Don't show dynamic progress updates
137
137
  --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)
138
138
  --reporter-options Pass extra options to the reporter (as JSON string, see example)
139
139
  --no-exit-code Always exit with code zero (0)
140
140
  --max-issues Maximum number of issues before non-zero exit code (default: 0)
141
- --debug Show debug output
141
+ -d, --debug Show debug output
142
142
  --debug-file-filter Filter for files in debug output (regex as string)
143
143
  --performance Measure count and running time of expensive functions and display stats table
144
144
  --h, --help Print this help text
@@ -646,7 +646,27 @@ Many thanks to some of the early adopters of Knip:
646
646
  - [release-it][27]
647
647
  - [Template TypeScript Node Package][28]
648
648
 
649
- ## Knip?!
649
+ ## 🐣 Super Secret Easter Egg Boost 🚀
650
+
651
+ Running Knip on large workspaces with many packages may feel a bit sluggish. Knip looks up `.gitignore` files and uses
652
+ them to filter out matching entry and project files. This increases correctness. However, you might want to disable that
653
+ with `--no-gitignore` and enjoy a significant performance boost. Depending on the contents of the `.gitignore` files,
654
+ the reported issues may be the same. To help determine whether this trade-off might be worth it for you, first check the
655
+ difference in unused files:
656
+
657
+ ```shell
658
+ diff <(knip --no-gitignore --include files) <(knip --include files)
659
+ ```
660
+
661
+ And to measure the difference of this flag in seconds:
662
+
663
+ ```shell
664
+ SECONDS=0; knip > /dev/null; t1=$SECONDS; SECONDS=0; knip --no-gitignore > /dev/null; t2=$SECONDS; echo "Difference: $((t1 - t2)) seconds"
665
+ ```
666
+
667
+ ⏲️ Analysis on a large project went from 33 down to 9 seconds (that's >70% faster). Happy Easter! 🐣
668
+
669
+ ## Knip
650
670
 
651
671
  Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
652
672
  for the job. I'm motivated to make Knip perfectly suited for the job of cutting projects to perfection! ✂️
@@ -5,7 +5,7 @@ import { ROOT_WORKSPACE_NAME, DEFAULT_EXTENSIONS, KNIP_CONFIG_LOCATIONS } from '
5
5
  import { defaultRules } from './issues/initializers.js';
6
6
  import * as plugins from './plugins/index.js';
7
7
  import { arrayify, compact } from './util/array.js';
8
- import parsedArgs from './util/cli-arguments.js';
8
+ import parsedArgValues from './util/cli-arguments.js';
9
9
  import { partitionCompilers } from './util/compilers.js';
10
10
  import { ConfigurationError } from './util/errors.js';
11
11
  import { findFile, loadJSON } from './util/fs.js';
@@ -16,7 +16,7 @@ import { getKeysByValue } from './util/object.js';
16
16
  import { join, relative, toPosix } from './util/path.js';
17
17
  import { toCamelCase } from './util/plugin.js';
18
18
  import { byPathDepth } from './util/workspace.js';
19
- const { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [], dependencies = false, exports = false, } = parsedArgs.values;
19
+ const { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [], dependencies = false, exports = false, } = parsedArgValues;
20
20
  const workspaceArg = rawWorkspaceArg ? toPosix(rawWorkspaceArg).replace(/^\.\//, '').replace(/\/$/, '') : undefined;
21
21
  const getDefaultWorkspaceConfig = (extensions) => {
22
22
  const exts = [...DEFAULT_EXTENSIONS, ...(extensions ?? [])].map(ext => ext.slice(1)).join(',');
@@ -211,7 +211,7 @@ export class ConfigurationChief {
211
211
  getDescendentWorkspaces(name) {
212
212
  return this.getAllWorkspaces()
213
213
  .filter(workspaceName => workspaceName !== name)
214
- .filter(workspaceName => name === ROOT_WORKSPACE_NAME || workspaceName.startsWith(name));
214
+ .filter(workspaceName => name === ROOT_WORKSPACE_NAME || workspaceName.startsWith(name + '/'));
215
215
  }
216
216
  getIgnoredWorkspaces() {
217
217
  const ignored = this.config.ignoreWorkspaces;
package/dist/cli.js CHANGED
@@ -2,14 +2,14 @@
2
2
  import './util/register.js';
3
3
  import prettyMilliseconds from 'pretty-ms';
4
4
  import reporters from './reporters/index.js';
5
- import parsedArgs, { helpText } from './util/cli-arguments.js';
6
- import { isKnownError, ConfigurationError } from './util/errors.js';
5
+ import parsedArgValues, { helpText } from './util/cli-arguments.js';
6
+ import { isKnownError, getKnownError, isConfigurationError, hasCause } from './util/errors.js';
7
7
  import { _load } from './util/loader.js';
8
8
  import { cwd, resolve } from './util/path.js';
9
9
  import { Performance } from './util/Performance.js';
10
10
  import { version } from './version.js';
11
11
  import { main } from './index.js';
12
- const { debug: isDebug = false, help: isHelp, 'max-issues': maxIssues = '0', 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = false, performance: isObservePerf = false, production: isProduction = false, reporter = 'symbols', 'reporter-options': reporterOptions = '', strict: isStrict = false, tsConfig, version: isVersion, } = parsedArgs.values;
12
+ const { debug: isDebug = false, help: isHelp, 'max-issues': maxIssues = '0', 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = false, performance: isObservePerf = false, production: isProduction = false, reporter = 'symbols', 'reporter-options': reporterOptions = '', strict: isStrict = false, tsConfig, version: isVersion, } = parsedArgValues;
13
13
  if (isHelp) {
14
14
  console.log(helpText);
15
15
  process.exit(0);
@@ -47,10 +47,11 @@ const run = async () => {
47
47
  }
48
48
  catch (error) {
49
49
  if (error instanceof Error && isKnownError(error)) {
50
- console.error(error.message);
51
- if (error.cause instanceof Error)
52
- console.error('Reason:', error.cause.message);
53
- if (error instanceof ConfigurationError)
50
+ const knownError = getKnownError(error);
51
+ console.error(knownError.message);
52
+ if (hasCause(knownError))
53
+ console.error('Reason:', knownError.cause.message);
54
+ if (isConfigurationError(knownError))
54
55
  console.log('\n' + helpText);
55
56
  process.exit(1);
56
57
  }
@@ -1,5 +1 @@
1
- type Options = {
2
- cwd: string;
3
- };
4
- export declare const fallback: (configFilePath: string, { cwd }: Options) => Promise<string[]>;
5
- export {};
1
+ export declare const fallback: (configFilePath: string) => any;
@@ -1,19 +1,13 @@
1
- import { compact } from '../../util/array.js';
2
- import { resolvePluginPackageName, getDependenciesFromSettings } from './helpers.js';
3
- export const fallback = async (configFilePath, { cwd }) => {
4
- const { ESLint } = await import('eslint');
5
- const engine = new ESLint({ cwd, overrideConfigFile: configFilePath, useEslintrc: false });
6
- const jsConfig = await engine.calculateConfigForFile('__placeholder__.js');
7
- const tsConfig = await engine.calculateConfigForFile('__placeholder__.ts');
8
- const tsxConfig = await engine.calculateConfigForFile('__placeholder__.tsx');
9
- const dependencies = [jsConfig, tsConfig, tsxConfig].map(config => {
10
- if (!config)
11
- return [];
12
- const plugins = config.plugins?.map(resolvePluginPackageName) ?? [];
13
- const parsers = config.parser ? [config.parser] : [];
14
- const extraParsers = config.parserOptions?.babelOptions?.presets ?? [];
15
- const settings = config.settings ? getDependenciesFromSettings(config.settings) : [];
16
- return [...parsers, ...extraParsers, ...plugins, ...settings];
17
- });
18
- return compact(dependencies.flat());
19
- };
1
+ import createJITI from 'jiti';
2
+ import transform from 'jiti/dist/babel.js';
3
+ import { timerify } from '../../util/Performance.js';
4
+ const rushstackMatch = /require\(("|')@rushstack\/(eslint-config\/patch|eslint-patch)\/modern-module-resolution("|')\)/;
5
+ const jiti = createJITI(process.cwd(), {
6
+ cache: false,
7
+ transform: (opts) => {
8
+ opts.source = opts.source.replace(rushstackMatch, '');
9
+ return transform(opts);
10
+ },
11
+ });
12
+ const load = (configFilePath) => jiti(configFilePath);
13
+ export const fallback = timerify(load);
@@ -8,6 +8,4 @@ type GetDependenciesDeep = (configFilePath: string, dependencies: Set<string>, o
8
8
  manifest: Manifest;
9
9
  }) => Promise<Set<string>>;
10
10
  export declare const getDependenciesDeep: GetDependenciesDeep;
11
- export declare const resolvePluginPackageName: (pluginName: string) => string;
12
- export declare const getDependenciesFromSettings: (settings?: ESLintConfig['settings']) => string[];
13
11
  export {};
@@ -6,8 +6,6 @@ import { _resolve } from '../../util/require.js';
6
6
  import { fallback } from './fallback.js';
7
7
  const getDependencies = (config) => {
8
8
  const extendsSpecifiers = config.extends ? [config.extends].flat().map(resolveExtendsSpecifier) : [];
9
- if (extendsSpecifiers.includes('eslint-plugin-prettier'))
10
- extendsSpecifiers.push('eslint-config-prettier');
11
9
  const plugins = config.plugins ? config.plugins.map(resolvePluginPackageName) : [];
12
10
  const parser = config.parser;
13
11
  const extraParsers = config.parserOptions?.babelOptions?.presets ?? [];
@@ -17,21 +15,11 @@ const getDependencies = (config) => {
17
15
  };
18
16
  export const getDependenciesDeep = async (configFilePath, dependencies = new Set(), options) => {
19
17
  const addAll = (deps) => deps.forEach(dependency => dependencies.add(dependency));
20
- let config = configFilePath.endsWith('package.json') ? options.manifest.eslintConfig : undefined;
21
- if (!config) {
22
- try {
23
- config = await load(configFilePath);
24
- }
25
- catch (err) {
26
- if (err instanceof Error && err.cause instanceof Error && /Failed to patch ESLint/.test(err.cause.message)) {
27
- const dependencies = await fallback(configFilePath, options);
28
- addAll(dependencies);
29
- }
30
- else {
31
- throw err;
32
- }
33
- }
34
- }
18
+ const config = configFilePath.endsWith('package.json')
19
+ ? options.manifest.eslintConfig
20
+ : /(\.(jsonc?|ya?ml)|rc)$/.test(configFilePath)
21
+ ? await load(configFilePath)
22
+ : await fallback(configFilePath);
35
23
  if (config) {
36
24
  if (config.extends) {
37
25
  for (const extend of [config.extends].flat()) {
@@ -48,7 +36,7 @@ export const getDependenciesDeep = async (configFilePath, dependencies = new Set
48
36
  return dependencies;
49
37
  };
50
38
  const resolvePackageName = (namespace, pluginName) => {
51
- return pluginName.includes(namespace + '-')
39
+ return pluginName.includes(namespace + '-') || pluginName.endsWith(`/${namespace}`)
52
40
  ? pluginName
53
41
  : pluginName.startsWith('@')
54
42
  ? pluginName.includes('/')
@@ -56,7 +44,7 @@ const resolvePackageName = (namespace, pluginName) => {
56
44
  : `${pluginName}/${namespace}`
57
45
  : `${namespace}-${pluginName}`;
58
46
  };
59
- export const resolvePluginPackageName = (pluginName) => resolvePackageName('eslint-plugin', pluginName);
47
+ const resolvePluginPackageName = (pluginName) => resolvePackageName('eslint-plugin', pluginName);
60
48
  const resolveExtendsSpecifier = (specifier) => {
61
49
  if (isInternal(specifier))
62
50
  return;
@@ -80,7 +68,7 @@ const getImportPluginDependencies = (settings) => {
80
68
  .filter(key => key !== 'node')
81
69
  .map(key => (knownKeys.includes(key) ? `eslint-import-resolver-${key}` : key));
82
70
  };
83
- export const getDependenciesFromSettings = (settings = {}) => {
71
+ const getDependenciesFromSettings = (settings = {}) => {
84
72
  return compact(Object.entries(settings).reduce((packageNames, [settingKey, settings]) => {
85
73
  if (/^import\/(parsers|resolvers)?/.test(settingKey) && typeof settings !== 'string') {
86
74
  return [...packageNames, ...getImportPluginDependencies(settings)];
@@ -1,8 +1,8 @@
1
1
  import { performance, PerformanceObserver } from 'node:perf_hooks';
2
2
  import EasyTable from 'easy-table';
3
3
  import Summary from 'summary';
4
- import parsedArgs from './cli-arguments.js';
5
- const { performance: isEnabled = false } = parsedArgs.values;
4
+ import parsedArgValues from './cli-arguments.js';
5
+ const { performance: isEnabled = false } = parsedArgValues;
6
6
  export const timerify = fn => (isEnabled ? performance.timerify(fn) : fn);
7
7
  export class Performance {
8
8
  isEnabled;
@@ -1,27 +1,24 @@
1
- export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no tests, devDependencies, exported types)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n --workspace Analyze a single workspace (default: analyze all configured workspaces)\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n --no-progress Don't show dynamic progress updates\n --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n --debug Show debug output\n --debug-file-filter Filter for files in debug output (regex as string)\n --performance Measure count and running time of expensive functions and display stats table\n --h, --help Print this help text\n --V, version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --debug --debug-file-filter '(specific|particular)-module'\n\nMore documentation and bug reports: https://github.com/webpro/knip";
1
+ export declare const helpText = "\u2702\uFE0F Find unused files, dependencies and exports in your JavaScript and TypeScript projects\n\nUsage: knip [options]\n\nOptions:\n -c, --config [file] Configuration file path (default: [.]knip.json[c], knip.js, knip.ts or package.json#knip)\n -t, --tsConfig [file] TypeScript configuration path (default: tsconfig.json)\n --production Analyze only production source files (e.g. no tests, devDependencies, exported types)\n --strict Consider only direct dependencies of workspace (not devDependencies, not other workspaces)\n --workspace Analyze a single workspace (default: analyze all configured workspaces)\n --no-gitignore Don't use .gitignore\n --include Report only provided issue type(s), can be comma-separated or repeated (1)\n --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)\n --dependencies Shortcut for --include dependencies,unlisted,unresolved\n --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates\n -n, --no-progress Don't show dynamic progress updates\n --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)\n --reporter-options Pass extra options to the reporter (as JSON string, see example)\n --no-exit-code Always exit with code zero (0)\n --max-issues Maximum number of issues before non-zero exit code (default: 0)\n -d, --debug Show debug output\n --debug-file-filter Filter for files in debug output (regex as string)\n --performance Measure count and running time of expensive functions and display stats table\n --h, --help Print this help text\n --V, version Print version\n\n(1) Issue types: files, dependencies, unlisted, unresolved, exports, nsExports, classMembers, types, nsTypes, enumMembers, duplicates\n\nExamples:\n\n$ knip\n$ knip --production\n$ knip --workspace packages/client --include files,dependencies\n$ knip -c ./config/knip.json --reporter compact\n$ knip --reporter codeowners --reporter-options '{\"path\":\".github/CODEOWNERS\"}'\n$ knip --debug --debug-file-filter '(specific|particular)-module'\n\nMore documentation and bug reports: https://github.com/webpro/knip";
2
2
  declare const _default: {
3
- values: {
4
- config: string | undefined;
5
- debug: boolean | undefined;
6
- 'debug-file-filter': string | undefined;
7
- dependencies: boolean | undefined;
8
- exclude: string[] | undefined;
9
- exports: boolean | undefined;
10
- help: boolean | undefined;
11
- include: string[] | undefined;
12
- 'max-issues': string | undefined;
13
- 'no-exit-code': boolean | undefined;
14
- 'no-gitignore': boolean | undefined;
15
- 'no-progress': boolean | undefined;
16
- performance: boolean | undefined;
17
- production: boolean | undefined;
18
- reporter: string | undefined;
19
- 'reporter-options': string | undefined;
20
- strict: boolean | undefined;
21
- tsConfig: string | undefined;
22
- version: boolean | undefined;
23
- workspace: string | undefined;
24
- };
25
- positionals: [];
3
+ config: string | undefined;
4
+ debug: boolean | undefined;
5
+ 'debug-file-filter': string | undefined;
6
+ dependencies: boolean | undefined;
7
+ exclude: string[] | undefined;
8
+ exports: boolean | undefined;
9
+ help: boolean | undefined;
10
+ include: string[] | undefined;
11
+ 'max-issues': string | undefined;
12
+ 'no-exit-code': boolean | undefined;
13
+ 'no-gitignore': boolean | undefined;
14
+ 'no-progress': boolean | undefined;
15
+ performance: boolean | undefined;
16
+ production: boolean | undefined;
17
+ reporter: string | undefined;
18
+ 'reporter-options': string | undefined;
19
+ strict: boolean | undefined;
20
+ tsConfig: string | undefined;
21
+ version: boolean | undefined;
22
+ workspace: string | undefined;
26
23
  };
27
24
  export default _default;
@@ -14,12 +14,12 @@ Options:
14
14
  --exclude Exclude provided issue type(s) from report, can be comma-separated or repeated (1)
15
15
  --dependencies Shortcut for --include dependencies,unlisted,unresolved
16
16
  --exports Shortcut for --include exports,nsExports,classMembers,types,nsTypes,enumMembers,duplicates
17
- --no-progress Don't show dynamic progress updates
17
+ -n, --no-progress Don't show dynamic progress updates
18
18
  --reporter Select reporter: symbols, compact, codeowners, json (default: symbols)
19
19
  --reporter-options Pass extra options to the reporter (as JSON string, see example)
20
20
  --no-exit-code Always exit with code zero (0)
21
21
  --max-issues Maximum number of issues before non-zero exit code (default: 0)
22
- --debug Show debug output
22
+ -d, --debug Show debug output
23
23
  --debug-file-filter Filter for files in debug output (regex as string)
24
24
  --performance Measure count and running time of expensive functions and display stats table
25
25
  --h, --help Print this help text
@@ -37,27 +37,39 @@ $ knip --reporter codeowners --reporter-options '{"path":".github/CODEOWNERS"}'
37
37
  $ knip --debug --debug-file-filter '(specific|particular)-module'
38
38
 
39
39
  More documentation and bug reports: https://github.com/webpro/knip`;
40
- export default parseArgs({
41
- options: {
42
- config: { type: 'string', short: 'c' },
43
- debug: { type: 'boolean' },
44
- 'debug-file-filter': { type: 'string' },
45
- dependencies: { type: 'boolean' },
46
- exclude: { type: 'string', multiple: true },
47
- exports: { type: 'boolean' },
48
- help: { type: 'boolean', short: 'h' },
49
- include: { type: 'string', multiple: true },
50
- 'max-issues': { type: 'string' },
51
- 'no-exit-code': { type: 'boolean' },
52
- 'no-gitignore': { type: 'boolean' },
53
- 'no-progress': { type: 'boolean' },
54
- performance: { type: 'boolean' },
55
- production: { type: 'boolean' },
56
- reporter: { type: 'string' },
57
- 'reporter-options': { type: 'string' },
58
- strict: { type: 'boolean' },
59
- tsConfig: { type: 'string', short: 't' },
60
- version: { type: 'boolean', short: 'V' },
61
- workspace: { type: 'string' },
62
- },
63
- });
40
+ let parsedArgs;
41
+ try {
42
+ parsedArgs = parseArgs({
43
+ options: {
44
+ config: { type: 'string', short: 'c' },
45
+ debug: { type: 'boolean', short: 'd' },
46
+ 'debug-file-filter': { type: 'string' },
47
+ dependencies: { type: 'boolean' },
48
+ exclude: { type: 'string', multiple: true },
49
+ exports: { type: 'boolean' },
50
+ help: { type: 'boolean', short: 'h' },
51
+ include: { type: 'string', multiple: true },
52
+ 'max-issues': { type: 'string' },
53
+ 'no-exit-code': { type: 'boolean' },
54
+ 'no-gitignore': { type: 'boolean' },
55
+ 'no-progress': { type: 'boolean', short: 'n' },
56
+ performance: { type: 'boolean' },
57
+ production: { type: 'boolean' },
58
+ reporter: { type: 'string' },
59
+ 'reporter-options': { type: 'string' },
60
+ strict: { type: 'boolean' },
61
+ tsConfig: { type: 'string', short: 't' },
62
+ version: { type: 'boolean', short: 'V' },
63
+ workspace: { type: 'string' },
64
+ },
65
+ });
66
+ }
67
+ catch (error) {
68
+ if (error instanceof Error) {
69
+ console.error(error.message);
70
+ console.log('\n' + helpText);
71
+ process.exit(1);
72
+ }
73
+ throw error;
74
+ }
75
+ export default parsedArgs.values;
@@ -1,6 +1,6 @@
1
1
  import util from 'node:util';
2
- import parsedArgs from './cli-arguments.js';
3
- const { debug, 'debug-file-filter': debugFileFilter } = parsedArgs.values;
2
+ import parsedArgValues from './cli-arguments.js';
3
+ const { debug, 'debug-file-filter': debugFileFilter } = parsedArgValues;
4
4
  const IS_ENABLED = debug ?? false;
5
5
  const FILE_FILTER = debugFileFilter;
6
6
  const inspectOptions = { maxArrayLength: null, depth: null, colors: true };
@@ -1,5 +1,12 @@
1
+ interface ErrorWithCause extends Error {
2
+ cause: Error;
3
+ }
1
4
  export declare class ConfigurationError extends Error {
2
5
  }
3
6
  export declare class LoaderError extends Error {
4
7
  }
5
8
  export declare const isKnownError: (error: Error) => boolean;
9
+ export declare const hasCause: (error: Error) => error is ErrorWithCause;
10
+ export declare const isConfigurationError: (error: Error) => boolean;
11
+ export declare const getKnownError: (error: Error) => Error;
12
+ export {};
@@ -1,5 +1,14 @@
1
+ import { ZodError } from 'zod';
2
+ import { fromZodError } from 'zod-validation-error';
1
3
  export class ConfigurationError extends Error {
2
4
  }
3
5
  export class LoaderError extends Error {
4
6
  }
5
- export const isKnownError = (error) => error instanceof ConfigurationError || error instanceof LoaderError;
7
+ export const isKnownError = (error) => error instanceof ConfigurationError || error instanceof LoaderError || error instanceof ZodError;
8
+ export const hasCause = (error) => error.cause instanceof Error;
9
+ export const isConfigurationError = (error) => error instanceof ConfigurationError;
10
+ export const getKnownError = (error) => {
11
+ if (error instanceof ZodError)
12
+ return fromZodError(error);
13
+ return error;
14
+ };
package/dist/util/glob.js CHANGED
@@ -16,9 +16,13 @@ export const hasNoProductionSuffix = (pattern) => !pattern.endsWith('!');
16
16
  const removeProductionSuffix = (pattern) => pattern.replace(/!$/, '');
17
17
  const negatedLast = (pattern) => (pattern.startsWith('!') ? 1 : -1);
18
18
  const glob = async ({ cwd, workingDir = cwd, patterns, ignore = [], gitignore = true }) => {
19
+ if (patterns.length === 0)
20
+ return [];
19
21
  const relativePath = relative(cwd, workingDir);
20
22
  const prepend = (pattern) => prependDirToPattern(relativePath, pattern);
21
23
  const globPatterns = compact([patterns].flat().map(prepend).map(removeProductionSuffix)).sort(negatedLast);
24
+ if (globPatterns[0].startsWith('!'))
25
+ return [];
22
26
  const ignorePatterns = compact([...ignore, '**/node_modules/**']);
23
27
  debugLogObject(`Globbing (${relativePath || ROOT_WORKSPACE_NAME})`, { cwd, globPatterns, ignorePatterns });
24
28
  return globby(globPatterns, {
@@ -29,12 +33,16 @@ const glob = async ({ cwd, workingDir = cwd, patterns, ignore = [], gitignore =
29
33
  dot: true,
30
34
  });
31
35
  };
32
- const pureGlob = async ({ cwd, patterns, ignore = [], gitignore = true }) => globby(patterns, {
33
- cwd,
34
- ignore: [...ignore, '**/node_modules/**'],
35
- gitignore,
36
- absolute: true,
37
- });
36
+ const pureGlob = async ({ cwd, patterns, ignore = [], gitignore = true }) => {
37
+ if (patterns.length === 0)
38
+ return [];
39
+ return globby(patterns, {
40
+ cwd,
41
+ ignore: [...ignore, '**/node_modules/**'],
42
+ gitignore,
43
+ absolute: true,
44
+ });
45
+ };
38
46
  const firstGlob = async ({ cwd, patterns }) => {
39
47
  const stream = fg.stream(patterns.map(removeProductionSuffix), { cwd, ignore: ['**/node_modules/**'] });
40
48
  for await (const entry of stream) {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "2.6.1";
1
+ export declare const version = "2.7.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.6.1';
1
+ export const version = '2.7.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.6.1",
3
+ "version": "2.7.1",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
5
5
  "homepage": "https://github.com/webpro/knip",
6
6
  "repository": "github:webpro/knip",
@@ -56,7 +56,8 @@
56
56
  "strip-json-comments": "^5.0.0",
57
57
  "summary": "^2.1.0",
58
58
  "typescript": "^5.0.2",
59
- "zod": "^3.20.6"
59
+ "zod": "^3.20.6",
60
+ "zod-validation-error": "1.2.1"
60
61
  },
61
62
  "devDependencies": {
62
63
  "@jest/types": "29.5.0",