knip 2.2.4 → 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 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
- _Actually_, here's the full list of default extensions: `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`.
57
+ To be honest, here's the full list of default extensions: `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`.
58
58
 
59
- If this matches your project, you don't need any configuration. Not even a `knip.json` file.
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();
@@ -48,11 +48,13 @@ export const getDependenciesDeep = async (configFilePath, dependencies = new Set
48
48
  return dependencies;
49
49
  };
50
50
  const resolvePackageName = (namespace, pluginName) => {
51
- return pluginName.startsWith('@')
52
- ? pluginName.includes('/')
53
- ? pluginName.replace(/\//, `/${namespace}-`)
54
- : `${pluginName}/${namespace}`
55
- : `${namespace}-${pluginName}`;
51
+ return pluginName.includes(namespace)
52
+ ? pluginName
53
+ : pluginName.startsWith('@')
54
+ ? pluginName.includes('/')
55
+ ? pluginName.replace(/\//, `/${namespace}-`)
56
+ : `${pluginName}/${namespace}`
57
+ : `${namespace}-${pluginName}`;
56
58
  };
57
59
  export const resolvePluginPackageName = (pluginName) => resolvePackageName('eslint-plugin', pluginName);
58
60
  const resolveExtendsSpecifier = (specifier) => {
@@ -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 }) => {
@@ -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[]>;
@@ -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
+ };
@@ -1 +1,2 @@
1
1
  export declare const getValuesByKeyDeep: (obj: any, key: string) => unknown[];
2
+ export declare const getStringValues: (obj: any) => string[];
@@ -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.2.4";
1
+ export declare const version = "2.3.0";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.2.4';
1
+ export const version = '2.3.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "2.2.4",
3
+ "version": "2.3.0",
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",