knip 2.2.3 → 2.3.0
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 +20 -2
- package/dist/binaries/resolvers/fallback.js +1 -0
- package/dist/index.js +7 -1
- package/dist/plugins/eslint/helpers.js +14 -10
- package/dist/plugins/eslint/types.d.ts +2 -1
- package/dist/util/glob.d.ts +2 -2
- package/dist/util/glob.js +2 -1
- package/dist/util/modules.d.ts +2 -0
- package/dist/util/modules.js +23 -0
- package/dist/util/object.d.ts +1 -0
- package/dist/util/object.js +14 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,9 +54,19 @@ Knip has good defaults and you can run it without any configuration. Here's the
|
|
|
54
54
|
}
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
To be honest, here's the full list of default extensions: `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
### Entry Files
|
|
60
|
+
|
|
61
|
+
Knip looks for entry files at the default locations above, but also in other places:
|
|
62
|
+
|
|
63
|
+
- The `main`, `bin` and `exports` fields of `package.json`.
|
|
64
|
+
- [Plugins][2] such as for Next.js, Remix, Gatsby or Svelte define entry files so you don't have to.
|
|
65
|
+
- The `scripts` in package.json may also provide entry files that Knip can use.
|
|
66
|
+
- Knip does this for each [workspace][1] it finds.
|
|
67
|
+
|
|
68
|
+
In other words, Knip looks in many places and you may not need much configuration. When everything is according to
|
|
69
|
+
defaults you don't even need a `knip.json` file.
|
|
60
70
|
|
|
61
71
|
Larger projects tend to have more things customized, and therefore probably get more out of Knip with a configuration
|
|
62
72
|
file. Let's say you are using `.ts` files excusively and have all source files only in the `src` directory:
|
|
@@ -645,6 +655,12 @@ Many thanks to some of the early adopters of Knip:
|
|
|
645
655
|
Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
|
|
646
656
|
for the job. I'm motivated to make knip perfectly suited for the job of cutting projects to perfection! ✂️
|
|
647
657
|
|
|
658
|
+
## Contributors
|
|
659
|
+
|
|
660
|
+
Special thanks to the wonderful people who have contributed to this project:
|
|
661
|
+
|
|
662
|
+
[![Contributors][30]][29]
|
|
663
|
+
|
|
648
664
|
[1]: #workspaces-monorepos
|
|
649
665
|
[2]: #plugins
|
|
650
666
|
[3]: #compilers
|
|
@@ -673,6 +689,8 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
|
|
|
673
689
|
[26]: https://github.com/RebeccaStevens/is-immutable-type
|
|
674
690
|
[27]: https://github.com/release-it/release-it
|
|
675
691
|
[28]: https://github.com/JoshuaKGoldberg/template-typescript-node-package
|
|
692
|
+
[29]: https://github.com/webpro/knip/graphs/contributors
|
|
693
|
+
[30]: https://contrib.rocks/image?repo=webpro/knip
|
|
676
694
|
[plugin-ava]: ./src/plugins/ava
|
|
677
695
|
[plugin-babel]: ./src/plugins/babel
|
|
678
696
|
[plugin-capacitor]: ./src/plugins/capacitor
|
|
@@ -5,6 +5,7 @@ const withPositional = parsed => [parsed._[0], parsed.require].flat();
|
|
|
5
5
|
const withoutPositional = parsed => [parsed.require].flat();
|
|
6
6
|
const argFilters = {
|
|
7
7
|
'babel-node': withPositional,
|
|
8
|
+
esbuild: withPositional,
|
|
8
9
|
nodemon: withPositional,
|
|
9
10
|
'ts-node': withPositional,
|
|
10
11
|
zx: withPositional,
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { debugLogObject, debugLogArray, debugLog } from './util/debug.js';
|
|
|
10
10
|
import { LoaderError } from './util/errors.js';
|
|
11
11
|
import { findFile } from './util/fs.js';
|
|
12
12
|
import { _glob } from './util/glob.js';
|
|
13
|
-
import { getPackageNameFromFilePath, getPackageNameFromModuleSpecifier } from './util/modules.js';
|
|
13
|
+
import { getEntryPathFromManifest, getPackageNameFromFilePath, getPackageNameFromModuleSpecifier, } from './util/modules.js';
|
|
14
14
|
import { dirname, isInNodeModules, join, isInternal, isAbsolute } from './util/path.js';
|
|
15
15
|
import { _resolveSpecifier, _tryResolve } from './util/require.js';
|
|
16
16
|
import { _require } from './util/require.js';
|
|
@@ -95,6 +95,9 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
95
95
|
});
|
|
96
96
|
await worker.init();
|
|
97
97
|
const sharedGlobOptions = { cwd, workingDir: dir, gitignore, ignore: worker.getIgnorePatterns() };
|
|
98
|
+
const entryPathsFromManifest = await getEntryPathFromManifest(dir, manifest);
|
|
99
|
+
debugLogArray(`Found entry paths from manifest (${name})`, entryPathsFromManifest);
|
|
100
|
+
principal.addEntryPaths(entryPathsFromManifest);
|
|
98
101
|
if (isProduction) {
|
|
99
102
|
{
|
|
100
103
|
const patterns = worker.getProductionEntryFilePatterns();
|
|
@@ -201,6 +204,9 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
201
204
|
importedModule.isReExported = importItems.isReExported;
|
|
202
205
|
importedModule.isReExportedBy.add(filePath);
|
|
203
206
|
}
|
|
207
|
+
if (importItems.isDynamic) {
|
|
208
|
+
importedModule.isDynamic = importItems.isDynamic;
|
|
209
|
+
}
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
duplicate.forEach(symbols => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { compact } from '../../util/array.js';
|
|
2
|
+
import { getPackageNameFromModuleSpecifier } from '../../util/modules.js';
|
|
2
3
|
import { isAbsolute, isInternal, join, dirname } from '../../util/path.js';
|
|
3
4
|
import { load } from '../../util/plugin.js';
|
|
4
5
|
import { _resolve } from '../../util/require.js';
|
|
@@ -11,7 +12,8 @@ const getDependencies = (config) => {
|
|
|
11
12
|
const parser = config.parser;
|
|
12
13
|
const extraParsers = config.parserOptions?.babelOptions?.presets ?? [];
|
|
13
14
|
const settings = config.settings ? getDependenciesFromSettings(config.settings) : [];
|
|
14
|
-
|
|
15
|
+
const overrides = config.overrides ? [config.overrides].flat().flatMap(getDependencies) : [];
|
|
16
|
+
return compact([...extendsSpecifiers, ...plugins, parser, ...extraParsers, ...settings, ...overrides]);
|
|
15
17
|
};
|
|
16
18
|
export const getDependenciesDeep = async (configFilePath, dependencies = new Set(), options) => {
|
|
17
19
|
const addAll = (deps) => deps.forEach(dependency => dependencies.add(dependency));
|
|
@@ -41,28 +43,30 @@ export const getDependenciesDeep = async (configFilePath, dependencies = new Set
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
if (config.overrides)
|
|
45
|
-
for (const override of [config.overrides].flat())
|
|
46
|
-
addAll(getDependencies(override));
|
|
47
46
|
addAll(getDependencies(config));
|
|
48
47
|
}
|
|
49
48
|
return dependencies;
|
|
50
49
|
};
|
|
51
50
|
const resolvePackageName = (namespace, pluginName) => {
|
|
52
|
-
return pluginName.
|
|
53
|
-
? pluginName
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
return pluginName.includes(namespace)
|
|
52
|
+
? pluginName
|
|
53
|
+
: pluginName.startsWith('@')
|
|
54
|
+
? pluginName.includes('/')
|
|
55
|
+
? pluginName.replace(/\//, `/${namespace}-`)
|
|
56
|
+
: `${pluginName}/${namespace}`
|
|
57
|
+
: `${namespace}-${pluginName}`;
|
|
57
58
|
};
|
|
58
59
|
export const resolvePluginPackageName = (pluginName) => resolvePackageName('eslint-plugin', pluginName);
|
|
59
60
|
const resolveExtendsSpecifier = (specifier) => {
|
|
60
61
|
if (isInternal(specifier))
|
|
61
62
|
return;
|
|
62
63
|
if (specifier.includes(':')) {
|
|
63
|
-
const
|
|
64
|
+
const strippedSpecifier = specifier.replace(/(^plugin:|:.+$)/, '').replace(/\/(eslint-)?recommended$/, '');
|
|
65
|
+
const pluginName = getPackageNameFromModuleSpecifier(strippedSpecifier);
|
|
64
66
|
if (pluginName === 'eslint')
|
|
65
67
|
return;
|
|
68
|
+
if (pluginName.includes('eslint-'))
|
|
69
|
+
return pluginName;
|
|
66
70
|
return resolvePackageName('eslint-plugin', pluginName);
|
|
67
71
|
}
|
|
68
72
|
return specifier.includes('eslint') ? specifier : resolvePackageName('eslint-config', specifier);
|
|
@@ -15,8 +15,9 @@ type BaseConfig = {
|
|
|
15
15
|
settings?: Settings;
|
|
16
16
|
rules?: Rules;
|
|
17
17
|
};
|
|
18
|
-
type OverrideConfig = BaseConfig & {
|
|
18
|
+
export type OverrideConfig = BaseConfig & {
|
|
19
19
|
files: string[];
|
|
20
|
+
overrides: OverrideConfig;
|
|
20
21
|
};
|
|
21
22
|
export type ESLintConfig = BaseConfig & {
|
|
22
23
|
env?: Record<string, boolean>;
|
package/dist/util/glob.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ interface BaseGlobOptions {
|
|
|
7
7
|
cwd: string;
|
|
8
8
|
patterns: string[];
|
|
9
9
|
ignore?: string[];
|
|
10
|
+
gitignore?: boolean;
|
|
10
11
|
}
|
|
11
12
|
interface GlobOptions extends BaseGlobOptions {
|
|
12
13
|
workingDir?: string;
|
|
13
|
-
gitignore?: boolean;
|
|
14
14
|
}
|
|
15
15
|
export declare const _glob: ({ cwd, workingDir, patterns, ignore, gitignore }: GlobOptions) => Promise<string[]>;
|
|
16
|
-
export declare const _pureGlob: ({ cwd, patterns, ignore }: BaseGlobOptions) => Promise<string[]>;
|
|
16
|
+
export declare const _pureGlob: ({ cwd, patterns, ignore, gitignore }: BaseGlobOptions) => Promise<string[]>;
|
|
17
17
|
export declare const _firstGlob: ({ cwd, patterns }: BaseGlobOptions) => Promise<string | Buffer | undefined>;
|
|
18
18
|
export declare const _dirGlob: ({ cwd, patterns }: BaseGlobOptions) => Promise<string[]>;
|
|
19
19
|
export {};
|
package/dist/util/glob.js
CHANGED
|
@@ -29,9 +29,10 @@ const glob = async ({ cwd, workingDir = cwd, patterns, ignore = [], gitignore =
|
|
|
29
29
|
dot: true,
|
|
30
30
|
});
|
|
31
31
|
};
|
|
32
|
-
const pureGlob = async ({ cwd, patterns, ignore = [] }) => globby(patterns, {
|
|
32
|
+
const pureGlob = async ({ cwd, patterns, ignore = [], gitignore = true }) => globby(patterns, {
|
|
33
33
|
cwd,
|
|
34
34
|
ignore: [...ignore, '**/node_modules/**'],
|
|
35
|
+
gitignore,
|
|
35
36
|
absolute: true,
|
|
36
37
|
});
|
|
37
38
|
const firstGlob = async ({ cwd, patterns }) => {
|
package/dist/util/modules.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { PackageJson } from '@npmcli/package-json';
|
|
1
2
|
export declare const getPackageNameFromModuleSpecifier: (moduleSpecifier: string) => string;
|
|
2
3
|
export declare const getPackageNameFromFilePath: (value: string) => string;
|
|
3
4
|
export declare const stripBinary: (command: string) => string;
|
|
4
5
|
export declare const isDefinitelyTyped: (packageName: string) => boolean;
|
|
5
6
|
export declare const getDefinitelyTypedFor: (packageName: string) => string;
|
|
6
7
|
export declare const getPackageFromDefinitelyTyped: (typedDependency: string) => string;
|
|
8
|
+
export declare const getEntryPathFromManifest: (dir: string, manifest: PackageJson) => Promise<string[]>;
|
package/dist/util/modules.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { _pureGlob } from './glob.js';
|
|
2
|
+
import { getStringValues } from './object.js';
|
|
1
3
|
import { toPosix } from './path.js';
|
|
2
4
|
export const getPackageNameFromModuleSpecifier = (moduleSpecifier) => {
|
|
3
5
|
const parts = moduleSpecifier.split('/').slice(0, 2);
|
|
@@ -28,3 +30,24 @@ export const getPackageFromDefinitelyTyped = (typedDependency) => {
|
|
|
28
30
|
}
|
|
29
31
|
return typedDependency;
|
|
30
32
|
};
|
|
33
|
+
export const getEntryPathFromManifest = (dir, manifest) => {
|
|
34
|
+
const { main, bin, exports } = manifest;
|
|
35
|
+
const entryPaths = new Set();
|
|
36
|
+
if (typeof main === 'string')
|
|
37
|
+
entryPaths.add(main);
|
|
38
|
+
if (bin) {
|
|
39
|
+
if (typeof bin === 'string')
|
|
40
|
+
entryPaths.add(bin);
|
|
41
|
+
if (typeof bin === 'object')
|
|
42
|
+
Object.values(bin).forEach(bin => entryPaths.add(bin));
|
|
43
|
+
}
|
|
44
|
+
if (exports) {
|
|
45
|
+
if (typeof exports === 'string') {
|
|
46
|
+
entryPaths.add(exports);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
getStringValues(exports).forEach(item => entryPaths.add(item));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return _pureGlob({ cwd: dir, patterns: Array.from(entryPaths) });
|
|
53
|
+
};
|
package/dist/util/object.d.ts
CHANGED
package/dist/util/object.js
CHANGED
|
@@ -13,3 +13,17 @@ export const getValuesByKeyDeep = (obj, key) => {
|
|
|
13
13
|
}
|
|
14
14
|
return objects;
|
|
15
15
|
};
|
|
16
|
+
export const getStringValues = (obj) => {
|
|
17
|
+
let values = [];
|
|
18
|
+
for (const prop in obj) {
|
|
19
|
+
if (obj[prop]) {
|
|
20
|
+
if (typeof obj[prop] === 'string') {
|
|
21
|
+
values.push(obj[prop]);
|
|
22
|
+
}
|
|
23
|
+
else if (typeof obj[prop] === 'object') {
|
|
24
|
+
values = values.concat(getStringValues(obj[prop]));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return values;
|
|
29
|
+
};
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.
|
|
1
|
+
export declare const version = "2.3.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.
|
|
1
|
+
export const version = '2.3.0';
|
package/package.json
CHANGED